diff --git a/.changeset/angry-wombats-marry.md b/.changeset/angry-wombats-marry.md new file mode 100644 index 0000000000000..ceb6caa6c8734 --- /dev/null +++ b/.changeset/angry-wombats-marry.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/proxyd': minor +--- + +Fixed JSON-RPC 2.0 specification compliance by adding the optional data field on an RPCError diff --git a/.changeset/chatty-impalas-report.md b/.changeset/chatty-impalas-report.md new file mode 100644 index 0000000000000..d4e9641a706b7 --- /dev/null +++ b/.changeset/chatty-impalas-report.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/contracts-bedrock': patch +--- + +Use uint64 for arithmetic in XDM's baseGas diff --git a/.changeset/chilly-cups-agree.md b/.changeset/chilly-cups-agree.md new file mode 100644 index 0000000000000..48cbd057c7add --- /dev/null +++ b/.changeset/chilly-cups-agree.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/sdk': patch +--- + +Adds contract addresses for the Bedrock Alpha testnet diff --git a/.changeset/five-grapes-march.md b/.changeset/five-grapes-march.md new file mode 100644 index 0000000000000..ffe3948f6595b --- /dev/null +++ b/.changeset/five-grapes-march.md @@ -0,0 +1,6 @@ +--- +'@eth-optimism/contracts-bedrock': patch +'@eth-optimism/sdk': patch +--- + +Rename the event emitted in the L2ToL1MessagePasser diff --git a/.changeset/green-doors-brake.md b/.changeset/green-doors-brake.md new file mode 100644 index 0000000000000..e72b467890516 --- /dev/null +++ b/.changeset/green-doors-brake.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/contracts-periphery': patch +--- + +Goerli nft bridge deployment diff --git a/.changeset/khaki-bottles-matter.md b/.changeset/khaki-bottles-matter.md new file mode 100644 index 0000000000000..c117f06510c86 --- /dev/null +++ b/.changeset/khaki-bottles-matter.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/l2geth': patch +--- + +add --rpc.evmtimeout flag to configure timeout for eth_call diff --git a/.changeset/lazy-drinks-drop.md b/.changeset/lazy-drinks-drop.md new file mode 100644 index 0000000000000..a3cff834f722e --- /dev/null +++ b/.changeset/lazy-drinks-drop.md @@ -0,0 +1,6 @@ +--- +'@eth-optimism/integration-tests': patch +'@eth-optimism/contracts-periphery': patch +--- + +Fix erc721 factory to match erc21 factory diff --git a/.changeset/lemon-files-rescue.md b/.changeset/lemon-files-rescue.md new file mode 100644 index 0000000000000..b680e03b571e7 --- /dev/null +++ b/.changeset/lemon-files-rescue.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/indexer': minor +--- + +Bedrock support diff --git a/.changeset/loud-pigs-hang.md b/.changeset/loud-pigs-hang.md new file mode 100644 index 0000000000000..bf22bd689f9d1 --- /dev/null +++ b/.changeset/loud-pigs-hang.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/proxyd': minor +--- + +Adds new Redis rate limiter diff --git a/.changeset/mighty-planets-pump.md b/.changeset/mighty-planets-pump.md new file mode 100644 index 0000000000000..e76acb600e398 --- /dev/null +++ b/.changeset/mighty-planets-pump.md @@ -0,0 +1,5 @@ +--- +"@eth-optimism/contracts-periphery": patch +--- + +mainnet nft bridge deployments diff --git a/.changeset/poor-singers-dance.md b/.changeset/poor-singers-dance.md new file mode 100644 index 0000000000000..db205f9fd28f4 --- /dev/null +++ b/.changeset/poor-singers-dance.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/contracts-bedrock': patch +--- + +Removes an unnecessary initializer parameter in the L200 diff --git a/.changeset/red-trains-run.md b/.changeset/red-trains-run.md new file mode 100644 index 0000000000000..c46e1853a35c9 --- /dev/null +++ b/.changeset/red-trains-run.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/endpoint-monitor': major +--- + +Initial release of endpoint monitor diff --git a/.changeset/serious-pianos-complain.md b/.changeset/serious-pianos-complain.md new file mode 100644 index 0000000000000..19123eb69295e --- /dev/null +++ b/.changeset/serious-pianos-complain.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/ci-builder': patch +--- + +Pin slither version to 0.9.0 diff --git a/.circleci/config.yml b/.circleci/config.yml index 94060ca51e959..229d39f293810 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -145,7 +145,7 @@ jobs: working_directory: packages/contracts-bedrock - run: name: upload coverage - command: codecov --verbose --clean --flag contracts-bedrock-forge + command: codecov --verbose --clean --flag contracts-bedrock-tests environment: FOUNDRY_PROFILE: ci - run: @@ -190,6 +190,9 @@ jobs: description: Regex matching dependent packages type: string default: this-package-does-not-exist + coverage_flag: + description: Coverage flag name + type: string docker: - image: ethereumoptimism/ci-builder:latest resource_class: large @@ -214,9 +217,7 @@ jobs: working_directory: packages/<> - run: name: Upload coverage - command: | - echo <> # TEMP for debugging - codecov --verbose --clean --flag <> + command: codecov --verbose --clean --flag <> bedrock-go-tests: docker: @@ -286,9 +287,14 @@ jobs: gotestsum --junitfile /test-results/op-batcher.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... working_directory: op-batcher - run: - name: test op-e2e + name: test op-e2e (WS) + command: | + gotestsum --format standard-verbose --junitfile /test-results/op-e2e.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + working_directory: op-e2e + - run: + name: test op-e2e (HTTP) command: | - gotestsum --junitfile /test-results/op-e2e.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + OP_E2E_USE_HTTP=true gotestsum --junitfile /test-results/op-e2e.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... working_directory: op-e2e - run: name: test op-service @@ -426,7 +432,7 @@ jobs: name: Test command: | mkdir -p /test-results - gotestsum --junitfile /test-results/tests.xml + DB_USER=postgres gotestsum --junitfile /test-results/tests.xml working_directory: <> - when: condition: @@ -632,17 +638,20 @@ workflows: - yarn-monorepo - js-lint-test: name: common-ts-tests + coverage_flag: common-ts-tests package_name: common-ts requires: - yarn-monorepo - js-lint-test: name: contracts-tests + coverage_flag: contracts-tests package_name: contracts dependencies: hardhat-deploy-config requires: - yarn-monorepo - js-lint-test: name: core-utils-tests + coverage_flag: core-utils-tests package_name: core-utils requires: - yarn-monorepo @@ -654,54 +663,63 @@ workflows: - yarn-monorepo - js-lint-test: name: actor-tests-tests + coverage_flag: actor-tests-tests package_name: actor-tests dependencies: "(core-utils|sdk)" requires: - yarn-monorepo - js-lint-test: name: contracts-governance-tests + coverage_flag: contracts-governance-tests package_name: contracts-governance dependencies: "(core-utils|sdk)" requires: - yarn-monorepo - js-lint-test: name: contracts-periphery-tests + coverage_flag: contracts-periphery-tests package_name: contracts-periphery dependencies: "(contracts|contracts-bedrock|core-utils|hardhat-deploy-config)" requires: - yarn-monorepo - js-lint-test: name: dtl-tests + coverage_flag: dtl-tests package_name: data-transport-layer dependencies: "(common-ts|contracts|core-utils)" requires: - yarn-monorepo - js-lint-test: name: drippie-mon-tests + coverage_flag: drippie-mon-tests package_name: drippie-mon dependencies: "(common-ts|contracts-periphery|core-utils|sdk)" requires: - yarn-monorepo - js-lint-test: name: fault-detector-tests + coverage_flag: fault-detector-tests package_name: fault-detector dependencies: "(common-ts|contracts|core-utils|sdk)" requires: - yarn-monorepo - js-lint-test: name: message-relayer-tests + coverage_flag: message-relayer-tests package_name: message-relayer dependencies: "(common-ts|core-utils|sdk)" requires: - yarn-monorepo - js-lint-test: name: replica-healthcheck-tests + coverage_flag: replica-healthcheck-tests package_name: replica-healthcheck dependencies: "(common-ts|core-utils)" requires: - yarn-monorepo - js-lint-test: name: sdk-tests + coverage_flag: sdk-tests package_name: sdk dependencies: "(contracts|core-utils)" requires: diff --git a/.github/mergify.yml b/.github/mergify.yml index d86a2e3cc3836..a16bd01467a4f 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -26,7 +26,7 @@ pull_request_rules: actions: queue: name: default - method: squash + method: merge - name: Add merge train label conditions: - "queue-position >= 0" @@ -99,7 +99,7 @@ pull_request_rules: - name: Nag changesets conditions: - and: - - 'files~=\.((?= c.CheckInterval { + return fmt.Errorf("%s must be less than %s", CheckDurationFlagName, CheckIntervalFlagName) + } + if err := c.LogConfig.Check(); err != nil { + return err + } + if err := c.MetricsConfig.Check(); err != nil { + return err + } + return nil +} + +func NewConfig(ctx *cli.Context) Config { + return Config{ + Providers: ctx.GlobalStringSlice(ProvidersFlagName), + CheckInterval: ctx.GlobalDuration(CheckIntervalFlagName), + CheckDuration: ctx.GlobalDuration(CheckDurationFlagName), + LogConfig: oplog.ReadCLIConfig(ctx), + MetricsConfig: opmetrics.ReadCLIConfig(ctx), + } +} + +// GetProviderConfigs fetches endpoint provider configurations from the environment +// Each provider should have a corresponding env var with the url, ex: PROVIDER1_URL= +func (c Config) GetProviderConfigs() []ProviderConfig { + result := make([]ProviderConfig, 0) + for _, provider := range c.Providers { + envKey := fmt.Sprintf("ENDPOINT_MONITOR_%s_URL", strings.ToUpper(provider)) + url := os.Getenv(envKey) + if url == "" { + panic(fmt.Sprintf("%s is not set", envKey)) + } + result = append(result, ProviderConfig{Name: provider, Url: url}) + } + return result +} diff --git a/endpoint-monitor/endpoint_monitor.go b/endpoint-monitor/endpoint_monitor.go new file mode 100644 index 0000000000000..6f1aa63ebcb1f --- /dev/null +++ b/endpoint-monitor/endpoint_monitor.go @@ -0,0 +1,132 @@ +package app + +import ( + "context" + "fmt" + "strings" + "time" + + oplog "github.com/ethereum-optimism/optimism/op-service/log" + opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" + "github.com/ethereum/go-ethereum/log" + "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus" + "github.com/urfave/cli" + + "github.com/ethereum-optimism/optimism/l2geth/core/types" + "github.com/ethereum-optimism/optimism/l2geth/ethclient" +) + +var ( + MetricWsSubscribeStatus = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "ws_subscribe_status", + Help: "eth_subscribe over websocket check status"}, + []string{"status", "provider", "error"}, + ) +) + +func Main(version string) func(cliCtx *cli.Context) error { + return func(cliCtx *cli.Context) error { + cfg := NewConfig(cliCtx) + if err := cfg.Check(); err != nil { + return fmt.Errorf("invalid CLI flags: %w", err) + } + + l := oplog.NewLogger(cfg.LogConfig) + + endpointMonitor := NewEndpointMonitor(cfg, l) + l.Info(fmt.Sprintf("starting endpoint monitor with checkInterval=%s checkDuration=%s", cfg.CheckInterval, cfg.CheckDuration)) + endpointMonitor.Start() + + ctx := context.Background() + registry := opmetrics.NewRegistry() + registry.MustRegister(MetricWsSubscribeStatus) + metricsCfg := cfg.MetricsConfig + + l.Info("starting metrics server", "addr", metricsCfg.ListenAddr, "port", metricsCfg.ListenPort) + if err := opmetrics.ListenAndServe(ctx, registry, metricsCfg.ListenAddr, metricsCfg.ListenPort); err != nil { + l.Error("error starting metrics server", err) + return err + } + + return nil + } +} + +type EndpointMonitor struct { + cfg Config + logger log.Logger +} + +func NewEndpointMonitor(cfg Config, l log.Logger) EndpointMonitor { + return EndpointMonitor{cfg: cfg, logger: l} +} + +func (e EndpointMonitor) Start() { + for _, providerConfig := range e.cfg.GetProviderConfigs() { + go e.runWebsocketCheckLoop(providerConfig, e.cfg.CheckInterval, e.cfg.CheckDuration) + } +} + +// getWrappingErrorMsg returns the most recently wrapped error message +// it's used in this case to get the error type reported by runSubscribeCallCheck +func getWrappingErrorMsg(err error) string { + cause := errors.Cause(err) + return strings.TrimSuffix(err.Error(), fmt.Sprintf(": %s", cause.Error())) +} + +// runWebsocketCheckLoop runs subscribe call checks every checkInterval and reports status metrics to prometheus +func (e EndpointMonitor) runWebsocketCheckLoop(p ProviderConfig, checkInterval, checkDuration time.Duration) { + ticker := time.NewTicker(checkInterval) + defer ticker.Stop() + + for { + e.logger.Info("running websocket check", "provider", p.Name) + err := e.runWebsocketCheck(p, checkDuration) + if err != nil { + errType := getWrappingErrorMsg(err) + MetricWsSubscribeStatus.With(prometheus.Labels{"provider": p.Name, "status": "error", "error": errType}).Inc() + e.logger.Error("finished websocket check", "provider", p.Name, "error", errType) + } else { + MetricWsSubscribeStatus.With(prometheus.Labels{"provider": p.Name, "status": "success", "error": ""}).Inc() + e.logger.Info("finished websocket check", "provider", p.Name) + } + <-ticker.C + } +} + +// runWebsocketCheck creates a client and subscribes to blockchain head notifications and returns any errors encountered for reporting +func (e EndpointMonitor) runWebsocketCheck(p ProviderConfig, duration time.Duration) error { + client, err := ethclient.Dial(p.Url) + if err != nil { + return errors.Wrap(err, "dial") + } + defer client.Close() + + headers := make(chan *types.Header) + sub, err := client.SubscribeNewHead(context.Background(), headers) + if err != nil { + return errors.Wrap(err, "eth_subscribe_failed") + } + + receivedData := false + ticker := time.NewTicker(duration) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + sub.Unsubscribe() + if !receivedData { + return errors.New("nodata") + } + return nil + case err := <-sub.Err(): + return errors.Wrap(err, "read") + case header := <-headers: + e.logger.Debug(header.Hash().Hex(), "provider", p.Name) + receivedData = true + } + } +} diff --git a/endpoint-monitor/go.mod b/endpoint-monitor/go.mod new file mode 100644 index 0000000000000..c79279c0fc64b --- /dev/null +++ b/endpoint-monitor/go.mod @@ -0,0 +1,40 @@ +module github.com/ethereum-optimism/optimism/endpoint-monitor + +go 1.18 + +require ( + github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220923210602-7121648c1f26 + github.com/ethereum-optimism/optimism/op-service v0.8.8 + github.com/ethereum/go-ethereum v1.10.23 + github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.13.0 + github.com/urfave/cli v1.22.9 +) + +require ( + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/elastic/gosigar v0.12.0 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect + github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect + golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect + golang.org/x/sys v0.0.0-20220701225701-179beb0bd1a1 // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect +) diff --git a/endpoint-monitor/go.sum b/endpoint-monitor/go.sum new file mode 100644 index 0000000000000..d9c181148d138 --- /dev/null +++ b/endpoint-monitor/go.sum @@ -0,0 +1,1063 @@ +cloud.google.com/go v0.26.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.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +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/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.42.6/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= +github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= +github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= +github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= +github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= +github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= +github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +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/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= +github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +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.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +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/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew 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/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +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/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220923210602-7121648c1f26 h1:wqYJm5ko5jzJx5wJM5BrN2nYxdgbIl1aIfFjyqA3T64= +github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220923210602-7121648c1f26/go.mod h1:Oj5A6Qs/Ao1SP17i3uKroyhz49q/ehagSXRAlvwaI5Y= +github.com/ethereum-optimism/optimism/op-service v0.8.8 h1:k5E78Zr2cGU0SwjoHpFXuC1eyfXhu3oKEOnDDaFi57I= +github.com/ethereum-optimism/optimism/op-service v0.8.8/go.mod h1:K0uybOhICTc2yfhrRj0cD1m7aPkOf5C9e6bUmvf4rGA= +github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= +github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= +github.com/ethereum/go-ethereum v1.10.23 h1:Xk8XAT4/UuqcjMLIMF+7imjkg32kfVFKoeyQDaO2yWM= +github.com/ethereum/go-ethereum v1.10.23/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +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/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= +github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= +github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/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/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +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.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +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= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +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.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +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 v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= +github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= +github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= +github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= +github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= +github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= +github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +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/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= +github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +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.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/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/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +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/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.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.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.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-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +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/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +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/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +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/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= +github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= +github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +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/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= +github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/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/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +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/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= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/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/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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/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-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +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-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/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-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/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-20190312061237-fead79001313/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-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/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-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/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-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/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-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/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-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/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-20220701225701-179beb0bd1a1 h1:+Lm8wRwJpsVpTHuM4tHTwgxjPzv/bjxsHt2cW5EY7XU= +golang.org/x/sys v0.0.0-20220701225701-179beb0bd1a1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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/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-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-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-20190206041539-40960b6deb8e/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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/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-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/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-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/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-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +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.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +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/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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.3/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.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +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= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +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.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/endpoint-monitor/package.json b/endpoint-monitor/package.json new file mode 100644 index 0000000000000..d1233b5efc6d4 --- /dev/null +++ b/endpoint-monitor/package.json @@ -0,0 +1,6 @@ +{ + "name": "@eth-optimism/endpoint-monitor", + "version": "0.0.0", + "private": true, + "dependencies": {} +} diff --git a/go.work b/go.work index 9855c351f286f..9063ead4c6308 100644 --- a/go.work +++ b/go.work @@ -3,6 +3,7 @@ go 1.18 use ( ./batch-submitter ./bss-core + ./endpoint-monitor ./gas-oracle ./indexer ./l2geth diff --git a/indexer/Makefile b/indexer/Makefile index 4817cb896c1a5..442021e4cf35b 100644 --- a/indexer/Makefile +++ b/indexer/Makefile @@ -7,6 +7,10 @@ LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) LDFLAGSSTRING +=-X main.GitVersion=$(GITVERSION) LDFLAGS := -ldflags "$(LDFLAGSSTRING)" +# Note: Requires legacy contracts to be built before +# running and binding-related Make targets. +SCC_ABI_ARTIFACT = ../packages/contracts/artifacts/contracts/L1/rollup/StateCommitmentChain.sol/StateCommitmentChain.json + indexer: env GO111MODULE=on go build -v $(LDFLAGS) ./cmd/indexer @@ -19,8 +23,28 @@ test: lint: golangci-lint run ./... +bindings: bindings-scc + +bindings-scc: + $(eval temp := $(shell mktemp)) + + cat $(SCC_ABI_ARTIFACT) \ + | jq -r .bytecode > $(temp) + + cat $(SCC_ABI_ARTIFACT) \ + | jq .abi \ + | abigen --pkg scc \ + --abi - \ + --out bindings/scc/statecommitmentchain.go \ + --type StateCommitmentChain \ + --bin $(temp) + + rm $(temp) + .PHONY: \ indexer \ + bindings \ + bindings-scc \ clean \ test \ lint diff --git a/indexer/bindings/legacy/scc/statecommitmentchain.go b/indexer/bindings/legacy/scc/statecommitmentchain.go new file mode 100644 index 0000000000000..a1f2ecfc5f579 --- /dev/null +++ b/indexer/bindings/legacy/scc/statecommitmentchain.go @@ -0,0 +1,862 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package scc + +import ( + "errors" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// Lib_OVMCodecChainBatchHeader is an auto generated low-level Go binding around an user-defined struct. +type Lib_OVMCodecChainBatchHeader struct { + BatchIndex *big.Int + BatchRoot [32]byte + BatchSize *big.Int + PrevTotalElements *big.Int + ExtraData []byte +} + +// Lib_OVMCodecChainInclusionProof is an auto generated low-level Go binding around an user-defined struct. +type Lib_OVMCodecChainInclusionProof struct { + Index *big.Int + Siblings [][32]byte +} + +// StateCommitmentChainMetaData contains all meta data concerning the StateCommitmentChain contract. +var StateCommitmentChainMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_libAddressManager\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_fraudProofWindow\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_sequencerPublishWindow\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_batchIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_batchRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_batchSize\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_prevTotalElements\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"StateBatchAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_batchIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_batchRoot\",\"type\":\"bytes32\"}],\"name\":\"StateBatchDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FRAUD_PROOF_WINDOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SEQUENCER_PUBLISH_WINDOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_batch\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"_shouldStartAtElement\",\"type\":\"uint256\"}],\"name\":\"appendStateBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batches\",\"outputs\":[{\"internalType\":\"contractIChainStorageContainer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"batchRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"batchSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevTotalElements\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"internalType\":\"structLib_OVMCodec.ChainBatchHeader\",\"name\":\"_batchHeader\",\"type\":\"tuple\"}],\"name\":\"deleteStateBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastSequencerTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_lastSequencerTimestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTotalBatches\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_totalBatches\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTotalElements\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_totalElements\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"batchRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"batchSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevTotalElements\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"internalType\":\"structLib_OVMCodec.ChainBatchHeader\",\"name\":\"_batchHeader\",\"type\":\"tuple\"}],\"name\":\"insideFraudProofWindow\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"_inside\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"libAddressManager\",\"outputs\":[{\"internalType\":\"contractLib_AddressManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_element\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"batchRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"batchSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevTotalElements\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"internalType\":\"structLib_OVMCodec.ChainBatchHeader\",\"name\":\"_batchHeader\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"siblings\",\"type\":\"bytes32[]\"}],\"internalType\":\"structLib_OVMCodec.ChainInclusionProof\",\"name\":\"_proof\",\"type\":\"tuple\"}],\"name\":\"verifyStateCommitment\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506040516120bb3803806120bb83398101604081905261002f9161005b565b600080546001600160a01b0319166001600160a01b03949094169390931790925560015560025561009e565b60008060006060848603121561007057600080fd5b83516001600160a01b038116811461008757600080fd5b602085015160409095015190969495509392505050565b61200e806100ad6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638ca5cbb911610081578063c17b291b1161005b578063c17b291b146101bb578063cfdf677e146101c4578063e561dddc146101cc57600080fd5b80638ca5cbb9146101805780639418bddd14610195578063b8e189ac146101a857600080fd5b80637aa63a86116100b25780637aa63a86146101595780637ad168a01461016f57806381eb62ef1461017757600080fd5b8063299ca478146100d9578063461a4478146101235780634d69ee5714610136575b600080fd5b6000546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f9610131366004611a1b565b6101d4565b610149610144366004611b8d565b610281565b604051901515815260200161011a565b610161610350565b60405190815260200161011a565b610161610369565b61016160025481565b61019361018e366004611c4a565b610382565b005b6101496101a3366004611c8f565b61075c565b6101936101b6366004611c8f565b610804565b61016160015481565b6100f96109c0565b6101616109e8565b600080546040517fbf40fac100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061022b908590600401611d2f565b60206040518083038186803b15801561024357600080fd5b505afa158015610257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027b9190611d64565b92915050565b600061028c83610a6f565b6102dd5760405162461bcd60e51b815260206004820152601560248201527f496e76616c6964206261746368206865616465722e000000000000000000000060448201526064015b60405180910390fd5b6102fa836020015185846000015185602001518760400151610b31565b6103465760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420696e636c7573696f6e2070726f6f662e000000000000000060448201526064016102d4565b5060019392505050565b60008061035b610d9f565b5064ffffffffff1692915050565b600080610374610d9f565b64ffffffffff169392505050565b61038a610350565b81146103fe5760405162461bcd60e51b815260206004820152603d60248201527f41637475616c20626174636820737461727420696e64657820646f6573206e6f60448201527f74206d6174636820657870656374656420737461727420696e6465782e00000060648201526084016102d4565b61043c6040518060400160405280600b81526020017f426f6e644d616e616765720000000000000000000000000000000000000000008152506101d4565b6040517f02ad4d2a00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff91909116906302ad4d2a9060240160206040518083038186803b1580156104a357600080fd5b505afa1580156104b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104db9190611d81565b61054d5760405162461bcd60e51b815260206004820152602f60248201527f50726f706f73657220646f6573206e6f74206861766520656e6f75676820636f60448201527f6c6c61746572616c20706f73746564000000000000000000000000000000000060648201526084016102d4565b60008251116105c45760405162461bcd60e51b815260206004820152602360248201527f43616e6e6f74207375626d697420616e20656d7074792073746174652062617460448201527f63682e000000000000000000000000000000000000000000000000000000000060648201526084016102d4565b6106026040518060400160405280601981526020017f43616e6f6e6963616c5472616e73616374696f6e436861696e000000000000008152506101d4565b73ffffffffffffffffffffffffffffffffffffffff16637aa63a866040518163ffffffff1660e01b815260040160206040518083038186803b15801561064757600080fd5b505afa15801561065b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067f9190611da3565b8251610689610350565b6106939190611deb565b111561072d5760405162461bcd60e51b815260206004820152604960248201527f4e756d626572206f6620737461746520726f6f74732063616e6e6f742065786360448201527f65656420746865206e756d626572206f662063616e6f6e6963616c207472616e60648201527f73616374696f6e732e0000000000000000000000000000000000000000000000608482015260a4016102d4565b6040805142602082015233818301528151808203830181526060909101909152610758908390610e43565b5050565b60008082608001518060200190518101906107779190611e03565b509050806107ed5760405162461bcd60e51b815260206004820152602560248201527f4261746368206865616465722074696d657374616d702063616e6e6f7420626560448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016102d4565b42600154826107fc9190611deb565b119392505050565b6108426040518060400160405280601181526020017f4f564d5f467261756456657269666965720000000000000000000000000000008152506101d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108e25760405162461bcd60e51b815260206004820152603b60248201527f537461746520626174636865732063616e206f6e6c792062652064656c65746560448201527f6420627920746865204f564d5f467261756456657269666965722e000000000060648201526084016102d4565b6108eb81610a6f565b6109375760405162461bcd60e51b815260206004820152601560248201527f496e76616c6964206261746368206865616465722e000000000000000000000060448201526064016102d4565b6109408161075c565b6109b4576040805162461bcd60e51b81526020600482015260248101919091527f537461746520626174636865732063616e206f6e6c792062652064656c65746560448201527f642077697468696e207468652066726175642070726f6f662077696e646f772e60648201526084016102d4565b6109bd816110e6565b50565b60006109e3604051806060016040528060218152602001611fb8602191396101d4565b905090565b60006109f26109c0565b73ffffffffffffffffffffffffffffffffffffffff16631f7b6d326040518163ffffffff1660e01b815260040160206040518083038186803b158015610a3757600080fd5b505afa158015610a4b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e39190611da3565b6000610a796109c0565b82516040517f9507d39a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9290921691639507d39a91610ad19160040190815260200190565b60206040518083038186803b158015610ae957600080fd5b505afa158015610afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b219190611da3565b610b2a83611317565b1492915050565b6000808211610ba85760405162461bcd60e51b815260206004820152603760248201527f4c69625f4d65726b6c65547265653a20546f74616c206c6561766573206d757360448201527f742062652067726561746572207468616e207a65726f2e00000000000000000060648201526084016102d4565b818410610c1c5760405162461bcd60e51b8152602060048201526024808201527f4c69625f4d65726b6c65547265653a20496e646578206f7574206f6620626f7560448201527f6e64732e0000000000000000000000000000000000000000000000000000000060648201526084016102d4565b610c258261135d565b835114610cc05760405162461bcd60e51b815260206004820152604d60248201527f4c69625f4d65726b6c65547265653a20546f74616c207369626c696e6773206460448201527f6f6573206e6f7420636f72726563746c7920636f72726573706f6e6420746f2060648201527f746f74616c206c65617665732e00000000000000000000000000000000000000608482015260a4016102d4565b8460005b8451811015610d92578560011660011415610d2b57848181518110610ceb57610ceb611e33565b602002602001015182604051602001610d0e929190918252602082015260400190565b604051602081830303815290604052805190602001209150610d79565b81858281518110610d3e57610d3e611e33565b6020026020010151604051602001610d60929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b60019590951c9480610d8a81611e62565b915050610cc4565b5090951495945050505050565b6000806000610dac6109c0565b73ffffffffffffffffffffffffffffffffffffffff1663ccf8f9696040518163ffffffff1660e01b815260040160206040518083038186803b158015610df157600080fd5b505afa158015610e05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e299190611e9b565b64ffffffffff602882901c169460509190911c9350915050565b6000610e836040518060400160405280600c81526020017f4f564d5f50726f706f73657200000000000000000000000000000000000000008152506101d4565b9050600080610e90610d9f565b90925090503373ffffffffffffffffffffffffffffffffffffffff84161415610eba575042610f69565b426002548264ffffffffff16610ed09190611deb565b10610f695760405162461bcd60e51b815260206004820152604360248201527f43616e6e6f74207075626c69736820737461746520726f6f747320776974686960448201527f6e207468652073657175656e636572207075626c69636174696f6e2077696e6460648201527f6f772e0000000000000000000000000000000000000000000000000000000000608482015260a4016102d4565b60006040518060a00160405280610f7e6109e8565b8152602001610f8c88611443565b8152602001875181526020018464ffffffffff16815260200186815250905080600001517f16be4c5129a4e03cf3350262e181dc02ddfb4a6008d925368c0899fcd97ca9c58260200151836040015184606001518560800151604051610ff59493929190611edd565b60405180910390a26110056109c0565b73ffffffffffffffffffffffffffffffffffffffff16632015276c61102983611317565b61104e846040015185606001516110409190611deb565b602887811b91909117901b90565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092527fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000166024820152604401600060405180830381600087803b1580156110c657600080fd5b505af11580156110da573d6000803e3d6000fd5b50505050505050505050565b6110ee6109c0565b73ffffffffffffffffffffffffffffffffffffffff16631f7b6d326040518163ffffffff1660e01b815260040160206040518083038186803b15801561113357600080fd5b505afa158015611147573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116b9190611da3565b8151106111ba5760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420626174636820696e6465782e00000000000000000000000060448201526064016102d4565b6111c381610a6f565b61120f5760405162461bcd60e51b815260206004820152601560248201527f496e76616c6964206261746368206865616465722e000000000000000000000060448201526064016102d4565b6112176109c0565b8151606083015173ffffffffffffffffffffffffffffffffffffffff929092169163167fd681919060281b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092527fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000166024820152604401600060405180830381600087803b1580156112ba57600080fd5b505af11580156112ce573d6000803e3d6000fd5b5050505080600001517f8747b69ce8fdb31c3b9b0a67bd8049ad8c1a69ea417b69b12174068abd9cbd64826020015160405161130c91815260200190565b60405180910390a250565b600081602001518260400151836060015184608001516040516020016113409493929190611edd565b604051602081830303815290604052805190602001209050919050565b60008082116113d45760405162461bcd60e51b815260206004820152603060248201527f4c69625f4d65726b6c65547265653a2043616e6e6f7420636f6d70757465206360448201527f65696c286c6f675f3229206f6620302e0000000000000000000000000000000060648201526084016102d4565b81600114156113e557506000919050565b81600060805b600181106114235780611401600180831b611f0c565b901b83161561141b576114148183611deb565b92811c9291505b60011c6113eb565b506001811b841461143c57611439600182611deb565b90505b9392505050565b6000808251116114bb5760405162461bcd60e51b815260206004820152603460248201527f4c69625f4d65726b6c65547265653a204d7573742070726f766964652061742060448201527f6c65617374206f6e65206c65616620686173682e00000000000000000000000060648201526084016102d4565b8151600114156114e757816000815181106114d8576114d8611e33565b60200260200101519050919050565b60408051610200810182527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381527f633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d60208201527f890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d818301527f3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd86060808301919091527fecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da60808301527fdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da560a08301527f617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d760c08301527f292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead60e08301527fe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e106101008301527f7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f826101208301527fe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e836365166101408301527f3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c6101608301527fad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e6101808301527fa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab6101a08301527f4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c8626101c08301527f2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf106101e083015282518381529081018352909160009190602082018180368337505085519192506000918291508180805b60018411156118fd57611798600285611f52565b91506117a5600285611f66565b600114905060005b82811015611851578a6117c1826002611f7a565b815181106117d1576117d1611e33565b602002602001015196508a8160026117e99190611f7a565b6117f4906001611deb565b8151811061180457611804611e33565b6020026020010151955086602089015285604089015287805190602001208b828151811061183457611834611e33565b60209081029190910101528061184981611e62565b9150506117ad565b5080156118cd5789611864600186611f0c565b8151811061187457611874611e33565b6020026020010151955087836010811061189057611890611e33565b602002015160001b945085602088015284604088015286805190602001208a83815181106118c0576118c0611e33565b6020026020010181815250505b806118d95760006118dc565b60015b6118e99060ff1683611deb565b9350826118f581611e62565b935050611784565b8960008151811061191057611910611e33565b602002602001015198505050505050505050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561199d5761199d611927565b604052919050565b600067ffffffffffffffff8311156119bf576119bf611927565b6119f060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011601611956565b9050828152838383011115611a0457600080fd5b828260208301376000602084830101529392505050565b600060208284031215611a2d57600080fd5b813567ffffffffffffffff811115611a4457600080fd5b8201601f81018413611a5557600080fd5b611a64848235602084016119a5565b949350505050565b600060a08284031215611a7e57600080fd5b60405160a0810167ffffffffffffffff8282108183111715611aa257611aa2611927565b81604052829350843583526020850135602084015260408501356040840152606085013560608401526080850135915080821115611adf57600080fd5b508301601f81018513611af157600080fd5b611b00858235602084016119a5565b6080830152505092915050565b600082601f830112611b1e57600080fd5b8135602067ffffffffffffffff821115611b3a57611b3a611927565b8160051b611b49828201611956565b9283528481018201928281019087851115611b6357600080fd5b83870192505b84831015611b8257823582529183019190830190611b69565b979650505050505050565b600080600060608486031215611ba257600080fd5b83359250602084013567ffffffffffffffff80821115611bc157600080fd5b611bcd87838801611a6c565b93506040860135915080821115611be357600080fd5b9085019060408288031215611bf757600080fd5b604051604081018181108382111715611c1257611c12611927565b60405282358152602083013582811115611c2b57600080fd5b611c3789828601611b0d565b6020830152508093505050509250925092565b60008060408385031215611c5d57600080fd5b823567ffffffffffffffff811115611c7457600080fd5b611c8085828601611b0d565b95602094909401359450505050565b600060208284031215611ca157600080fd5b813567ffffffffffffffff811115611cb857600080fd5b611a6484828501611a6c565b6000815180845260005b81811015611cea57602081850181015186830182015201611cce565b81811115611cfc576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061143c6020830184611cc4565b73ffffffffffffffffffffffffffffffffffffffff811681146109bd57600080fd5b600060208284031215611d7657600080fd5b815161143c81611d42565b600060208284031215611d9357600080fd5b8151801515811461143c57600080fd5b600060208284031215611db557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611dfe57611dfe611dbc565b500190565b60008060408385031215611e1657600080fd5b825191506020830151611e2881611d42565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611e9457611e94611dbc565b5060010190565b600060208284031215611ead57600080fd5b81517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000008116811461143c57600080fd5b848152836020820152826040820152608060608201526000611f026080830184611cc4565b9695505050505050565b600082821015611f1e57611f1e611dbc565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611f6157611f61611f23565b500490565b600082611f7557611f75611f23565b500690565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611fb257611fb2611dbc565b50029056fe436861696e53746f72616765436f6e7461696e65722d5343432d62617463686573a2646970667358221220f97433bcdfea89f96da4dd35233c6b44aadecb94f82aab10226e964aff14127064736f6c63430008090033", +} + +// StateCommitmentChainABI is the input ABI used to generate the binding from. +// Deprecated: Use StateCommitmentChainMetaData.ABI instead. +var StateCommitmentChainABI = StateCommitmentChainMetaData.ABI + +// StateCommitmentChainBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use StateCommitmentChainMetaData.Bin instead. +var StateCommitmentChainBin = StateCommitmentChainMetaData.Bin + +// DeployStateCommitmentChain deploys a new Ethereum contract, binding an instance of StateCommitmentChain to it. +func DeployStateCommitmentChain(auth *bind.TransactOpts, backend bind.ContractBackend, _libAddressManager common.Address, _fraudProofWindow *big.Int, _sequencerPublishWindow *big.Int) (common.Address, *types.Transaction, *StateCommitmentChain, error) { + parsed, err := StateCommitmentChainMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(StateCommitmentChainBin), backend, _libAddressManager, _fraudProofWindow, _sequencerPublishWindow) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &StateCommitmentChain{StateCommitmentChainCaller: StateCommitmentChainCaller{contract: contract}, StateCommitmentChainTransactor: StateCommitmentChainTransactor{contract: contract}, StateCommitmentChainFilterer: StateCommitmentChainFilterer{contract: contract}}, nil +} + +// StateCommitmentChain is an auto generated Go binding around an Ethereum contract. +type StateCommitmentChain struct { + StateCommitmentChainCaller // Read-only binding to the contract + StateCommitmentChainTransactor // Write-only binding to the contract + StateCommitmentChainFilterer // Log filterer for contract events +} + +// StateCommitmentChainCaller is an auto generated read-only Go binding around an Ethereum contract. +type StateCommitmentChainCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StateCommitmentChainTransactor is an auto generated write-only Go binding around an Ethereum contract. +type StateCommitmentChainTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StateCommitmentChainFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type StateCommitmentChainFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StateCommitmentChainSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type StateCommitmentChainSession struct { + Contract *StateCommitmentChain // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// StateCommitmentChainCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type StateCommitmentChainCallerSession struct { + Contract *StateCommitmentChainCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// StateCommitmentChainTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type StateCommitmentChainTransactorSession struct { + Contract *StateCommitmentChainTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// StateCommitmentChainRaw is an auto generated low-level Go binding around an Ethereum contract. +type StateCommitmentChainRaw struct { + Contract *StateCommitmentChain // Generic contract binding to access the raw methods on +} + +// StateCommitmentChainCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type StateCommitmentChainCallerRaw struct { + Contract *StateCommitmentChainCaller // Generic read-only contract binding to access the raw methods on +} + +// StateCommitmentChainTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type StateCommitmentChainTransactorRaw struct { + Contract *StateCommitmentChainTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewStateCommitmentChain creates a new instance of StateCommitmentChain, bound to a specific deployed contract. +func NewStateCommitmentChain(address common.Address, backend bind.ContractBackend) (*StateCommitmentChain, error) { + contract, err := bindStateCommitmentChain(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &StateCommitmentChain{StateCommitmentChainCaller: StateCommitmentChainCaller{contract: contract}, StateCommitmentChainTransactor: StateCommitmentChainTransactor{contract: contract}, StateCommitmentChainFilterer: StateCommitmentChainFilterer{contract: contract}}, nil +} + +// NewStateCommitmentChainCaller creates a new read-only instance of StateCommitmentChain, bound to a specific deployed contract. +func NewStateCommitmentChainCaller(address common.Address, caller bind.ContractCaller) (*StateCommitmentChainCaller, error) { + contract, err := bindStateCommitmentChain(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &StateCommitmentChainCaller{contract: contract}, nil +} + +// NewStateCommitmentChainTransactor creates a new write-only instance of StateCommitmentChain, bound to a specific deployed contract. +func NewStateCommitmentChainTransactor(address common.Address, transactor bind.ContractTransactor) (*StateCommitmentChainTransactor, error) { + contract, err := bindStateCommitmentChain(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &StateCommitmentChainTransactor{contract: contract}, nil +} + +// NewStateCommitmentChainFilterer creates a new log filterer instance of StateCommitmentChain, bound to a specific deployed contract. +func NewStateCommitmentChainFilterer(address common.Address, filterer bind.ContractFilterer) (*StateCommitmentChainFilterer, error) { + contract, err := bindStateCommitmentChain(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &StateCommitmentChainFilterer{contract: contract}, nil +} + +// bindStateCommitmentChain binds a generic wrapper to an already deployed contract. +func bindStateCommitmentChain(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(StateCommitmentChainABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_StateCommitmentChain *StateCommitmentChainRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _StateCommitmentChain.Contract.StateCommitmentChainCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_StateCommitmentChain *StateCommitmentChainRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _StateCommitmentChain.Contract.StateCommitmentChainTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_StateCommitmentChain *StateCommitmentChainRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _StateCommitmentChain.Contract.StateCommitmentChainTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_StateCommitmentChain *StateCommitmentChainCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _StateCommitmentChain.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_StateCommitmentChain *StateCommitmentChainTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _StateCommitmentChain.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_StateCommitmentChain *StateCommitmentChainTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _StateCommitmentChain.Contract.contract.Transact(opts, method, params...) +} + +// FRAUDPROOFWINDOW is a free data retrieval call binding the contract method 0xc17b291b. +// +// Solidity: function FRAUD_PROOF_WINDOW() view returns(uint256) +func (_StateCommitmentChain *StateCommitmentChainCaller) FRAUDPROOFWINDOW(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "FRAUD_PROOF_WINDOW") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// FRAUDPROOFWINDOW is a free data retrieval call binding the contract method 0xc17b291b. +// +// Solidity: function FRAUD_PROOF_WINDOW() view returns(uint256) +func (_StateCommitmentChain *StateCommitmentChainSession) FRAUDPROOFWINDOW() (*big.Int, error) { + return _StateCommitmentChain.Contract.FRAUDPROOFWINDOW(&_StateCommitmentChain.CallOpts) +} + +// FRAUDPROOFWINDOW is a free data retrieval call binding the contract method 0xc17b291b. +// +// Solidity: function FRAUD_PROOF_WINDOW() view returns(uint256) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) FRAUDPROOFWINDOW() (*big.Int, error) { + return _StateCommitmentChain.Contract.FRAUDPROOFWINDOW(&_StateCommitmentChain.CallOpts) +} + +// SEQUENCERPUBLISHWINDOW is a free data retrieval call binding the contract method 0x81eb62ef. +// +// Solidity: function SEQUENCER_PUBLISH_WINDOW() view returns(uint256) +func (_StateCommitmentChain *StateCommitmentChainCaller) SEQUENCERPUBLISHWINDOW(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "SEQUENCER_PUBLISH_WINDOW") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SEQUENCERPUBLISHWINDOW is a free data retrieval call binding the contract method 0x81eb62ef. +// +// Solidity: function SEQUENCER_PUBLISH_WINDOW() view returns(uint256) +func (_StateCommitmentChain *StateCommitmentChainSession) SEQUENCERPUBLISHWINDOW() (*big.Int, error) { + return _StateCommitmentChain.Contract.SEQUENCERPUBLISHWINDOW(&_StateCommitmentChain.CallOpts) +} + +// SEQUENCERPUBLISHWINDOW is a free data retrieval call binding the contract method 0x81eb62ef. +// +// Solidity: function SEQUENCER_PUBLISH_WINDOW() view returns(uint256) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) SEQUENCERPUBLISHWINDOW() (*big.Int, error) { + return _StateCommitmentChain.Contract.SEQUENCERPUBLISHWINDOW(&_StateCommitmentChain.CallOpts) +} + +// Batches is a free data retrieval call binding the contract method 0xcfdf677e. +// +// Solidity: function batches() view returns(address) +func (_StateCommitmentChain *StateCommitmentChainCaller) Batches(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "batches") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Batches is a free data retrieval call binding the contract method 0xcfdf677e. +// +// Solidity: function batches() view returns(address) +func (_StateCommitmentChain *StateCommitmentChainSession) Batches() (common.Address, error) { + return _StateCommitmentChain.Contract.Batches(&_StateCommitmentChain.CallOpts) +} + +// Batches is a free data retrieval call binding the contract method 0xcfdf677e. +// +// Solidity: function batches() view returns(address) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) Batches() (common.Address, error) { + return _StateCommitmentChain.Contract.Batches(&_StateCommitmentChain.CallOpts) +} + +// GetLastSequencerTimestamp is a free data retrieval call binding the contract method 0x7ad168a0. +// +// Solidity: function getLastSequencerTimestamp() view returns(uint256 _lastSequencerTimestamp) +func (_StateCommitmentChain *StateCommitmentChainCaller) GetLastSequencerTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "getLastSequencerTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetLastSequencerTimestamp is a free data retrieval call binding the contract method 0x7ad168a0. +// +// Solidity: function getLastSequencerTimestamp() view returns(uint256 _lastSequencerTimestamp) +func (_StateCommitmentChain *StateCommitmentChainSession) GetLastSequencerTimestamp() (*big.Int, error) { + return _StateCommitmentChain.Contract.GetLastSequencerTimestamp(&_StateCommitmentChain.CallOpts) +} + +// GetLastSequencerTimestamp is a free data retrieval call binding the contract method 0x7ad168a0. +// +// Solidity: function getLastSequencerTimestamp() view returns(uint256 _lastSequencerTimestamp) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) GetLastSequencerTimestamp() (*big.Int, error) { + return _StateCommitmentChain.Contract.GetLastSequencerTimestamp(&_StateCommitmentChain.CallOpts) +} + +// GetTotalBatches is a free data retrieval call binding the contract method 0xe561dddc. +// +// Solidity: function getTotalBatches() view returns(uint256 _totalBatches) +func (_StateCommitmentChain *StateCommitmentChainCaller) GetTotalBatches(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "getTotalBatches") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetTotalBatches is a free data retrieval call binding the contract method 0xe561dddc. +// +// Solidity: function getTotalBatches() view returns(uint256 _totalBatches) +func (_StateCommitmentChain *StateCommitmentChainSession) GetTotalBatches() (*big.Int, error) { + return _StateCommitmentChain.Contract.GetTotalBatches(&_StateCommitmentChain.CallOpts) +} + +// GetTotalBatches is a free data retrieval call binding the contract method 0xe561dddc. +// +// Solidity: function getTotalBatches() view returns(uint256 _totalBatches) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) GetTotalBatches() (*big.Int, error) { + return _StateCommitmentChain.Contract.GetTotalBatches(&_StateCommitmentChain.CallOpts) +} + +// GetTotalElements is a free data retrieval call binding the contract method 0x7aa63a86. +// +// Solidity: function getTotalElements() view returns(uint256 _totalElements) +func (_StateCommitmentChain *StateCommitmentChainCaller) GetTotalElements(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "getTotalElements") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetTotalElements is a free data retrieval call binding the contract method 0x7aa63a86. +// +// Solidity: function getTotalElements() view returns(uint256 _totalElements) +func (_StateCommitmentChain *StateCommitmentChainSession) GetTotalElements() (*big.Int, error) { + return _StateCommitmentChain.Contract.GetTotalElements(&_StateCommitmentChain.CallOpts) +} + +// GetTotalElements is a free data retrieval call binding the contract method 0x7aa63a86. +// +// Solidity: function getTotalElements() view returns(uint256 _totalElements) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) GetTotalElements() (*big.Int, error) { + return _StateCommitmentChain.Contract.GetTotalElements(&_StateCommitmentChain.CallOpts) +} + +// InsideFraudProofWindow is a free data retrieval call binding the contract method 0x9418bddd. +// +// Solidity: function insideFraudProofWindow((uint256,bytes32,uint256,uint256,bytes) _batchHeader) view returns(bool _inside) +func (_StateCommitmentChain *StateCommitmentChainCaller) InsideFraudProofWindow(opts *bind.CallOpts, _batchHeader Lib_OVMCodecChainBatchHeader) (bool, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "insideFraudProofWindow", _batchHeader) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// InsideFraudProofWindow is a free data retrieval call binding the contract method 0x9418bddd. +// +// Solidity: function insideFraudProofWindow((uint256,bytes32,uint256,uint256,bytes) _batchHeader) view returns(bool _inside) +func (_StateCommitmentChain *StateCommitmentChainSession) InsideFraudProofWindow(_batchHeader Lib_OVMCodecChainBatchHeader) (bool, error) { + return _StateCommitmentChain.Contract.InsideFraudProofWindow(&_StateCommitmentChain.CallOpts, _batchHeader) +} + +// InsideFraudProofWindow is a free data retrieval call binding the contract method 0x9418bddd. +// +// Solidity: function insideFraudProofWindow((uint256,bytes32,uint256,uint256,bytes) _batchHeader) view returns(bool _inside) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) InsideFraudProofWindow(_batchHeader Lib_OVMCodecChainBatchHeader) (bool, error) { + return _StateCommitmentChain.Contract.InsideFraudProofWindow(&_StateCommitmentChain.CallOpts, _batchHeader) +} + +// LibAddressManager is a free data retrieval call binding the contract method 0x299ca478. +// +// Solidity: function libAddressManager() view returns(address) +func (_StateCommitmentChain *StateCommitmentChainCaller) LibAddressManager(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "libAddressManager") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// LibAddressManager is a free data retrieval call binding the contract method 0x299ca478. +// +// Solidity: function libAddressManager() view returns(address) +func (_StateCommitmentChain *StateCommitmentChainSession) LibAddressManager() (common.Address, error) { + return _StateCommitmentChain.Contract.LibAddressManager(&_StateCommitmentChain.CallOpts) +} + +// LibAddressManager is a free data retrieval call binding the contract method 0x299ca478. +// +// Solidity: function libAddressManager() view returns(address) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) LibAddressManager() (common.Address, error) { + return _StateCommitmentChain.Contract.LibAddressManager(&_StateCommitmentChain.CallOpts) +} + +// Resolve is a free data retrieval call binding the contract method 0x461a4478. +// +// Solidity: function resolve(string _name) view returns(address) +func (_StateCommitmentChain *StateCommitmentChainCaller) Resolve(opts *bind.CallOpts, _name string) (common.Address, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "resolve", _name) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Resolve is a free data retrieval call binding the contract method 0x461a4478. +// +// Solidity: function resolve(string _name) view returns(address) +func (_StateCommitmentChain *StateCommitmentChainSession) Resolve(_name string) (common.Address, error) { + return _StateCommitmentChain.Contract.Resolve(&_StateCommitmentChain.CallOpts, _name) +} + +// Resolve is a free data retrieval call binding the contract method 0x461a4478. +// +// Solidity: function resolve(string _name) view returns(address) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) Resolve(_name string) (common.Address, error) { + return _StateCommitmentChain.Contract.Resolve(&_StateCommitmentChain.CallOpts, _name) +} + +// VerifyStateCommitment is a free data retrieval call binding the contract method 0x4d69ee57. +// +// Solidity: function verifyStateCommitment(bytes32 _element, (uint256,bytes32,uint256,uint256,bytes) _batchHeader, (uint256,bytes32[]) _proof) view returns(bool) +func (_StateCommitmentChain *StateCommitmentChainCaller) VerifyStateCommitment(opts *bind.CallOpts, _element [32]byte, _batchHeader Lib_OVMCodecChainBatchHeader, _proof Lib_OVMCodecChainInclusionProof) (bool, error) { + var out []interface{} + err := _StateCommitmentChain.contract.Call(opts, &out, "verifyStateCommitment", _element, _batchHeader, _proof) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// VerifyStateCommitment is a free data retrieval call binding the contract method 0x4d69ee57. +// +// Solidity: function verifyStateCommitment(bytes32 _element, (uint256,bytes32,uint256,uint256,bytes) _batchHeader, (uint256,bytes32[]) _proof) view returns(bool) +func (_StateCommitmentChain *StateCommitmentChainSession) VerifyStateCommitment(_element [32]byte, _batchHeader Lib_OVMCodecChainBatchHeader, _proof Lib_OVMCodecChainInclusionProof) (bool, error) { + return _StateCommitmentChain.Contract.VerifyStateCommitment(&_StateCommitmentChain.CallOpts, _element, _batchHeader, _proof) +} + +// VerifyStateCommitment is a free data retrieval call binding the contract method 0x4d69ee57. +// +// Solidity: function verifyStateCommitment(bytes32 _element, (uint256,bytes32,uint256,uint256,bytes) _batchHeader, (uint256,bytes32[]) _proof) view returns(bool) +func (_StateCommitmentChain *StateCommitmentChainCallerSession) VerifyStateCommitment(_element [32]byte, _batchHeader Lib_OVMCodecChainBatchHeader, _proof Lib_OVMCodecChainInclusionProof) (bool, error) { + return _StateCommitmentChain.Contract.VerifyStateCommitment(&_StateCommitmentChain.CallOpts, _element, _batchHeader, _proof) +} + +// AppendStateBatch is a paid mutator transaction binding the contract method 0x8ca5cbb9. +// +// Solidity: function appendStateBatch(bytes32[] _batch, uint256 _shouldStartAtElement) returns() +func (_StateCommitmentChain *StateCommitmentChainTransactor) AppendStateBatch(opts *bind.TransactOpts, _batch [][32]byte, _shouldStartAtElement *big.Int) (*types.Transaction, error) { + return _StateCommitmentChain.contract.Transact(opts, "appendStateBatch", _batch, _shouldStartAtElement) +} + +// AppendStateBatch is a paid mutator transaction binding the contract method 0x8ca5cbb9. +// +// Solidity: function appendStateBatch(bytes32[] _batch, uint256 _shouldStartAtElement) returns() +func (_StateCommitmentChain *StateCommitmentChainSession) AppendStateBatch(_batch [][32]byte, _shouldStartAtElement *big.Int) (*types.Transaction, error) { + return _StateCommitmentChain.Contract.AppendStateBatch(&_StateCommitmentChain.TransactOpts, _batch, _shouldStartAtElement) +} + +// AppendStateBatch is a paid mutator transaction binding the contract method 0x8ca5cbb9. +// +// Solidity: function appendStateBatch(bytes32[] _batch, uint256 _shouldStartAtElement) returns() +func (_StateCommitmentChain *StateCommitmentChainTransactorSession) AppendStateBatch(_batch [][32]byte, _shouldStartAtElement *big.Int) (*types.Transaction, error) { + return _StateCommitmentChain.Contract.AppendStateBatch(&_StateCommitmentChain.TransactOpts, _batch, _shouldStartAtElement) +} + +// DeleteStateBatch is a paid mutator transaction binding the contract method 0xb8e189ac. +// +// Solidity: function deleteStateBatch((uint256,bytes32,uint256,uint256,bytes) _batchHeader) returns() +func (_StateCommitmentChain *StateCommitmentChainTransactor) DeleteStateBatch(opts *bind.TransactOpts, _batchHeader Lib_OVMCodecChainBatchHeader) (*types.Transaction, error) { + return _StateCommitmentChain.contract.Transact(opts, "deleteStateBatch", _batchHeader) +} + +// DeleteStateBatch is a paid mutator transaction binding the contract method 0xb8e189ac. +// +// Solidity: function deleteStateBatch((uint256,bytes32,uint256,uint256,bytes) _batchHeader) returns() +func (_StateCommitmentChain *StateCommitmentChainSession) DeleteStateBatch(_batchHeader Lib_OVMCodecChainBatchHeader) (*types.Transaction, error) { + return _StateCommitmentChain.Contract.DeleteStateBatch(&_StateCommitmentChain.TransactOpts, _batchHeader) +} + +// DeleteStateBatch is a paid mutator transaction binding the contract method 0xb8e189ac. +// +// Solidity: function deleteStateBatch((uint256,bytes32,uint256,uint256,bytes) _batchHeader) returns() +func (_StateCommitmentChain *StateCommitmentChainTransactorSession) DeleteStateBatch(_batchHeader Lib_OVMCodecChainBatchHeader) (*types.Transaction, error) { + return _StateCommitmentChain.Contract.DeleteStateBatch(&_StateCommitmentChain.TransactOpts, _batchHeader) +} + +// StateCommitmentChainStateBatchAppendedIterator is returned from FilterStateBatchAppended and is used to iterate over the raw logs and unpacked data for StateBatchAppended events raised by the StateCommitmentChain contract. +type StateCommitmentChainStateBatchAppendedIterator struct { + Event *StateCommitmentChainStateBatchAppended // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StateCommitmentChainStateBatchAppendedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StateCommitmentChainStateBatchAppended) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StateCommitmentChainStateBatchAppended) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StateCommitmentChainStateBatchAppendedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StateCommitmentChainStateBatchAppendedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StateCommitmentChainStateBatchAppended represents a StateBatchAppended event raised by the StateCommitmentChain contract. +type StateCommitmentChainStateBatchAppended struct { + BatchIndex *big.Int + BatchRoot [32]byte + BatchSize *big.Int + PrevTotalElements *big.Int + ExtraData []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterStateBatchAppended is a free log retrieval operation binding the contract event 0x16be4c5129a4e03cf3350262e181dc02ddfb4a6008d925368c0899fcd97ca9c5. +// +// Solidity: event StateBatchAppended(uint256 indexed _batchIndex, bytes32 _batchRoot, uint256 _batchSize, uint256 _prevTotalElements, bytes _extraData) +func (_StateCommitmentChain *StateCommitmentChainFilterer) FilterStateBatchAppended(opts *bind.FilterOpts, _batchIndex []*big.Int) (*StateCommitmentChainStateBatchAppendedIterator, error) { + + var _batchIndexRule []interface{} + for _, _batchIndexItem := range _batchIndex { + _batchIndexRule = append(_batchIndexRule, _batchIndexItem) + } + + logs, sub, err := _StateCommitmentChain.contract.FilterLogs(opts, "StateBatchAppended", _batchIndexRule) + if err != nil { + return nil, err + } + return &StateCommitmentChainStateBatchAppendedIterator{contract: _StateCommitmentChain.contract, event: "StateBatchAppended", logs: logs, sub: sub}, nil +} + +// WatchStateBatchAppended is a free log subscription operation binding the contract event 0x16be4c5129a4e03cf3350262e181dc02ddfb4a6008d925368c0899fcd97ca9c5. +// +// Solidity: event StateBatchAppended(uint256 indexed _batchIndex, bytes32 _batchRoot, uint256 _batchSize, uint256 _prevTotalElements, bytes _extraData) +func (_StateCommitmentChain *StateCommitmentChainFilterer) WatchStateBatchAppended(opts *bind.WatchOpts, sink chan<- *StateCommitmentChainStateBatchAppended, _batchIndex []*big.Int) (event.Subscription, error) { + + var _batchIndexRule []interface{} + for _, _batchIndexItem := range _batchIndex { + _batchIndexRule = append(_batchIndexRule, _batchIndexItem) + } + + logs, sub, err := _StateCommitmentChain.contract.WatchLogs(opts, "StateBatchAppended", _batchIndexRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StateCommitmentChainStateBatchAppended) + if err := _StateCommitmentChain.contract.UnpackLog(event, "StateBatchAppended", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseStateBatchAppended is a log parse operation binding the contract event 0x16be4c5129a4e03cf3350262e181dc02ddfb4a6008d925368c0899fcd97ca9c5. +// +// Solidity: event StateBatchAppended(uint256 indexed _batchIndex, bytes32 _batchRoot, uint256 _batchSize, uint256 _prevTotalElements, bytes _extraData) +func (_StateCommitmentChain *StateCommitmentChainFilterer) ParseStateBatchAppended(log types.Log) (*StateCommitmentChainStateBatchAppended, error) { + event := new(StateCommitmentChainStateBatchAppended) + if err := _StateCommitmentChain.contract.UnpackLog(event, "StateBatchAppended", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// StateCommitmentChainStateBatchDeletedIterator is returned from FilterStateBatchDeleted and is used to iterate over the raw logs and unpacked data for StateBatchDeleted events raised by the StateCommitmentChain contract. +type StateCommitmentChainStateBatchDeletedIterator struct { + Event *StateCommitmentChainStateBatchDeleted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StateCommitmentChainStateBatchDeletedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StateCommitmentChainStateBatchDeleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StateCommitmentChainStateBatchDeleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StateCommitmentChainStateBatchDeletedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StateCommitmentChainStateBatchDeletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StateCommitmentChainStateBatchDeleted represents a StateBatchDeleted event raised by the StateCommitmentChain contract. +type StateCommitmentChainStateBatchDeleted struct { + BatchIndex *big.Int + BatchRoot [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterStateBatchDeleted is a free log retrieval operation binding the contract event 0x8747b69ce8fdb31c3b9b0a67bd8049ad8c1a69ea417b69b12174068abd9cbd64. +// +// Solidity: event StateBatchDeleted(uint256 indexed _batchIndex, bytes32 _batchRoot) +func (_StateCommitmentChain *StateCommitmentChainFilterer) FilterStateBatchDeleted(opts *bind.FilterOpts, _batchIndex []*big.Int) (*StateCommitmentChainStateBatchDeletedIterator, error) { + + var _batchIndexRule []interface{} + for _, _batchIndexItem := range _batchIndex { + _batchIndexRule = append(_batchIndexRule, _batchIndexItem) + } + + logs, sub, err := _StateCommitmentChain.contract.FilterLogs(opts, "StateBatchDeleted", _batchIndexRule) + if err != nil { + return nil, err + } + return &StateCommitmentChainStateBatchDeletedIterator{contract: _StateCommitmentChain.contract, event: "StateBatchDeleted", logs: logs, sub: sub}, nil +} + +// WatchStateBatchDeleted is a free log subscription operation binding the contract event 0x8747b69ce8fdb31c3b9b0a67bd8049ad8c1a69ea417b69b12174068abd9cbd64. +// +// Solidity: event StateBatchDeleted(uint256 indexed _batchIndex, bytes32 _batchRoot) +func (_StateCommitmentChain *StateCommitmentChainFilterer) WatchStateBatchDeleted(opts *bind.WatchOpts, sink chan<- *StateCommitmentChainStateBatchDeleted, _batchIndex []*big.Int) (event.Subscription, error) { + + var _batchIndexRule []interface{} + for _, _batchIndexItem := range _batchIndex { + _batchIndexRule = append(_batchIndexRule, _batchIndexItem) + } + + logs, sub, err := _StateCommitmentChain.contract.WatchLogs(opts, "StateBatchDeleted", _batchIndexRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StateCommitmentChainStateBatchDeleted) + if err := _StateCommitmentChain.contract.UnpackLog(event, "StateBatchDeleted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseStateBatchDeleted is a log parse operation binding the contract event 0x8747b69ce8fdb31c3b9b0a67bd8049ad8c1a69ea417b69b12174068abd9cbd64. +// +// Solidity: event StateBatchDeleted(uint256 indexed _batchIndex, bytes32 _batchRoot) +func (_StateCommitmentChain *StateCommitmentChainFilterer) ParseStateBatchDeleted(log types.Log) (*StateCommitmentChainStateBatchDeleted, error) { + event := new(StateCommitmentChainStateBatchDeleted) + if err := _StateCommitmentChain.contract.UnpackLog(event, "StateBatchDeleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/indexer/config.go b/indexer/config.go index b1c07ed495d7e..b6a096c79485c 100644 --- a/indexer/config.go +++ b/indexer/config.go @@ -4,6 +4,7 @@ import ( "errors" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/urfave/cli" @@ -20,15 +21,8 @@ var ( type Config struct { /* Required Params */ - // BuildEnv identifies the environment this binary is intended for, i.e. - // production, development, etc. - BuildEnv string - - // EthNetworkName identifies the intended Ethereum network. - EthNetworkName string - // ChainID identifies the chain being indexed. - ChainID int64 + ChainID uint64 // L1EthRpc is the HTTP provider URL for L1. L1EthRpc string @@ -36,8 +30,8 @@ type Config struct { // L2EthRpc is the HTTP provider URL for L1. L2EthRpc string - // L2GenesisBlockHash is the l2 genesis block hash. - L2GenesisBlockHash string + // L1AddressManagerAddress is the address of the address manager for L1. + L1AddressManagerAddress string // PollInterval is the delay between querying L2 for more transaction // and creating a new batch. @@ -68,22 +62,8 @@ type Config struct { // are printed using JSON. LogTerminal bool - // SentryEnable if true, logs any error messages to sentry. SentryDsn - // must also be set if SentryEnable is true. - SentryEnable bool - - // SentryDsn is the sentry Data Source Name. - SentryDsn string - - // SentryTraceRate the frequency with which Sentry should flush buffered - // events. - SentryTraceRate time.Duration - - // StartBlockNumber is the block number to start indexing from. - StartBlockNumber uint64 - - // StartBlockHash is the block hash to start indexing from. - StartBlockHash string + // L1StartBlockNumber is the block number to start indexing L1 from. + L1StartBlockNumber uint64 // ConfDepth is the number of confirmations after which headers are // considered confirmed. @@ -111,6 +91,13 @@ type Config struct { // DisableIndexer enables/disables the indexer. DisableIndexer bool + + // Bedrock enabled Bedrock indexing. + Bedrock bool + + BedrockL1StandardBridgeAddress common.Address + + BedrockOptimismPortalAddress common.Address } // NewConfig parses the Config from the provided flags or environment variables. @@ -118,33 +105,30 @@ type Config struct { func NewConfig(ctx *cli.Context) (Config, error) { cfg := Config{ /* Required Flags */ - BuildEnv: ctx.GlobalString(flags.BuildEnvFlag.Name), - EthNetworkName: ctx.GlobalString(flags.EthNetworkNameFlag.Name), - ChainID: ctx.GlobalInt64(flags.ChainIDFlag.Name), - L1EthRpc: ctx.GlobalString(flags.L1EthRPCFlag.Name), - L2EthRpc: ctx.GlobalString(flags.L2EthRPCFlag.Name), - L2GenesisBlockHash: ctx.GlobalString(flags.L2GenesisBlockHashFlag.Name), - DBHost: ctx.GlobalString(flags.DBHostFlag.Name), - DBPort: ctx.GlobalUint64(flags.DBPortFlag.Name), - DBUser: ctx.GlobalString(flags.DBUserFlag.Name), - DBPassword: ctx.GlobalString(flags.DBPasswordFlag.Name), - DBName: ctx.GlobalString(flags.DBNameFlag.Name), + ChainID: ctx.GlobalUint64(flags.ChainIDFlag.Name), + L1EthRpc: ctx.GlobalString(flags.L1EthRPCFlag.Name), + L2EthRpc: ctx.GlobalString(flags.L2EthRPCFlag.Name), + L1AddressManagerAddress: ctx.GlobalString(flags.L1AddressManagerAddressFlag.Name), + DBHost: ctx.GlobalString(flags.DBHostFlag.Name), + DBPort: ctx.GlobalUint64(flags.DBPortFlag.Name), + DBUser: ctx.GlobalString(flags.DBUserFlag.Name), + DBPassword: ctx.GlobalString(flags.DBPasswordFlag.Name), + DBName: ctx.GlobalString(flags.DBNameFlag.Name), /* Optional Flags */ - DisableIndexer: ctx.GlobalBool(flags.DisableIndexer.Name), - LogLevel: ctx.GlobalString(flags.LogLevelFlag.Name), - LogTerminal: ctx.GlobalBool(flags.LogTerminalFlag.Name), - SentryEnable: ctx.GlobalBool(flags.SentryEnableFlag.Name), - SentryDsn: ctx.GlobalString(flags.SentryDsnFlag.Name), - SentryTraceRate: ctx.GlobalDuration(flags.SentryTraceRateFlag.Name), - StartBlockNumber: ctx.GlobalUint64(flags.StartBlockNumberFlag.Name), - StartBlockHash: ctx.GlobalString(flags.StartBlockHashFlag.Name), - ConfDepth: ctx.GlobalUint64(flags.ConfDepthFlag.Name), - MaxHeaderBatchSize: ctx.GlobalUint64(flags.MaxHeaderBatchSizeFlag.Name), - MetricsServerEnable: ctx.GlobalBool(flags.MetricsServerEnableFlag.Name), - RESTHostname: ctx.GlobalString(flags.RESTHostnameFlag.Name), - RESTPort: ctx.GlobalUint64(flags.RESTPortFlag.Name), - MetricsHostname: ctx.GlobalString(flags.MetricsHostnameFlag.Name), - MetricsPort: ctx.GlobalUint64(flags.MetricsPortFlag.Name), + Bedrock: ctx.GlobalBool(flags.BedrockFlag.Name), + BedrockL1StandardBridgeAddress: common.HexToAddress(ctx.GlobalString(flags.BedrockL1StandardBridgeAddress.Name)), + BedrockOptimismPortalAddress: common.HexToAddress(ctx.GlobalString(flags.BedrockOptimismPortalAddress.Name)), + DisableIndexer: ctx.GlobalBool(flags.DisableIndexer.Name), + LogLevel: ctx.GlobalString(flags.LogLevelFlag.Name), + LogTerminal: ctx.GlobalBool(flags.LogTerminalFlag.Name), + L1StartBlockNumber: ctx.GlobalUint64(flags.L1StartBlockNumberFlag.Name), + ConfDepth: ctx.GlobalUint64(flags.ConfDepthFlag.Name), + MaxHeaderBatchSize: ctx.GlobalUint64(flags.MaxHeaderBatchSizeFlag.Name), + MetricsServerEnable: ctx.GlobalBool(flags.MetricsServerEnableFlag.Name), + RESTHostname: ctx.GlobalString(flags.RESTHostnameFlag.Name), + RESTPort: ctx.GlobalUint64(flags.RESTPortFlag.Name), + MetricsHostname: ctx.GlobalString(flags.MetricsHostnameFlag.Name), + MetricsPort: ctx.GlobalUint64(flags.MetricsPortFlag.Name), } err := ValidateConfig(&cfg) @@ -168,9 +152,8 @@ func ValidateConfig(cfg *Config) error { return err } - // Ensure the Sentry Data Source Name is set when using Sentry. - if cfg.SentryEnable && cfg.SentryDsn == "" { - return ErrSentryDSNNotSet + if cfg.Bedrock && (cfg.BedrockL1StandardBridgeAddress == common.Address{} || cfg.BedrockOptimismPortalAddress == common.Address{}) { + return errors.New("must specify l1 standard bridge and optimism portal addresses in bedrock mode") } return nil diff --git a/indexer/db/db.go b/indexer/db/db.go index fcfa060146a38..288d463834a6b 100644 --- a/indexer/db/db.go +++ b/indexer/db/db.go @@ -193,18 +193,14 @@ func (d *Database) AddIndexedL1Block(block *IndexedL1Block) error { const insertDepositStatement = ` INSERT INTO deposits - (guid, from_address, to_address, l1_token, l2_token, amount, tx_hash, log_index, l1_block_hash, data) + (guid, from_address, to_address, l1_token, l2_token, amount, tx_hash, log_index, block_hash, data) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ` - const insertWithdrawalStatement = ` - INSERT INTO withdrawals - (guid, from_address, to_address, l1_token, l2_token, amount, tx_hash, log_index, l1_block_hash, data) - VALUES - ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) - ON CONFLICT (tx_hash) - DO UPDATE SET l1_block_hash = $9; + const updateWithdrawalStatement = ` + UPDATE withdrawals SET (br_withdrawal_finalized_tx_hash, br_withdrawal_finalized_log_index, br_withdrawal_finalized_success) = ($1, $2, $3) + WHERE br_withdrawal_hash = $4 ` return txn(d.db, func(tx *sql.Tx) error { @@ -219,49 +215,39 @@ func (d *Database) AddIndexedL1Block(block *IndexedL1Block) error { return err } - if len(block.Deposits) == 0 { - return nil - } - - for _, deposit := range block.Deposits { - _, err = tx.Exec( - insertDepositStatement, - NewGUID(), - deposit.FromAddress.String(), - deposit.ToAddress.String(), - deposit.L1Token.String(), - deposit.L2Token.String(), - deposit.Amount.String(), - deposit.TxHash.String(), - deposit.LogIndex, - block.Hash.String(), - deposit.Data, - ) - if err != nil { - return err + if len(block.Deposits) > 0 { + for _, deposit := range block.Deposits { + _, err = tx.Exec( + insertDepositStatement, + NewGUID(), + deposit.FromAddress.String(), + deposit.ToAddress.String(), + deposit.L1Token.String(), + deposit.L2Token.String(), + deposit.Amount.String(), + deposit.TxHash.String(), + deposit.LogIndex, + block.Hash.String(), + deposit.Data, + ) + if err != nil { + return err + } } } - if len(block.Withdrawals) == 0 { - return nil - } - - for _, withdrawal := range block.Withdrawals { - _, err = tx.Exec( - insertWithdrawalStatement, - NewGUID(), - withdrawal.FromAddress.String(), - withdrawal.ToAddress.String(), - withdrawal.L1Token.String(), - withdrawal.L2Token.String(), - withdrawal.Amount.String(), - withdrawal.TxHash.String(), - withdrawal.LogIndex, - block.Hash.String(), - withdrawal.Data, - ) - if err != nil { - return err + if len(block.FinalizedWithdrawals) > 0 { + for _, wd := range block.FinalizedWithdrawals { + _, err = tx.Exec( + updateWithdrawalStatement, + wd.TxHash.String(), + wd.LogIndex, + wd.Success, + wd.WithdrawalHash.String(), + ) + if err != nil { + return err + } } } @@ -282,9 +268,9 @@ func (d *Database) AddIndexedL2Block(block *IndexedL2Block) error { const insertWithdrawalStatement = ` INSERT INTO withdrawals - (guid, from_address, to_address, l1_token, l2_token, amount, tx_hash, log_index, l2_block_hash, data) + (guid, from_address, to_address, l1_token, l2_token, amount, tx_hash, log_index, block_hash, data, br_withdrawal_hash) VALUES - ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) + ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) ` return txn(d.db, func(tx *sql.Tx) error { _, err := tx.Exec( @@ -315,6 +301,37 @@ func (d *Database) AddIndexedL2Block(block *IndexedL2Block) error { withdrawal.LogIndex, block.Hash.String(), withdrawal.Data, + nullableHash(withdrawal.BedrockHash), + ) + if err != nil { + return err + } + } + + return nil + }) +} + +// AddStateBatch inserts the state batches into the known state batches +// database. +func (d *Database) AddStateBatch(batches []StateBatch) error { + const insertStateBatchStatement = ` + INSERT INTO state_batches + (index, root, size, prev_total, extra_data, block_hash) + VALUES + ($1, $2, $3, $4, $5, $6) + ` + + return txn(d.db, func(tx *sql.Tx) error { + for _, sb := range batches { + _, err := tx.Exec( + insertStateBatchStatement, + sb.Index.Uint64(), + sb.Root.String(), + sb.Size.Uint64(), + sb.PrevTotal.Uint64(), + sb.ExtraData, + sb.BlockHash.String(), ) if err != nil { return err @@ -336,7 +353,7 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP l1_tokens.name, l1_tokens.symbol, l1_tokens.decimals, l1_blocks.number, l1_blocks.timestamp FROM deposits - INNER JOIN l1_blocks ON deposits.l1_block_hash=l1_blocks.hash + INNER JOIN l1_blocks ON deposits.block_hash=l1_blocks.hash INNER JOIN l1_tokens ON deposits.l1_token=l1_tokens.address WHERE deposits.from_address = $1 ORDER BY l1_blocks.timestamp LIMIT $2 OFFSET $3; ` @@ -375,7 +392,7 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP SELECT count(*) FROM deposits - INNER JOIN l1_blocks ON deposits.l1_block_hash=l1_blocks.hash + INNER JOIN l1_blocks ON deposits.block_hash=l1_blocks.hash INNER JOIN l1_tokens ON deposits.l1_token=l1_tokens.address WHERE deposits.from_address = $1; ` @@ -401,43 +418,54 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP }, nil } -// GetWithdrawalStatus returns the finalization status corresponding to the -// given withdrawal transaction hash. -func (d *Database) GetWithdrawalStatus(hash common.Hash) (*WithdrawalJSON, error) { - const selectWithdrawalStatement = ` +// GetWithdrawalBatch returns the StateBatch corresponding to the given +// withdrawal transaction hash. +func (d *Database) GetWithdrawalBatch(hash common.Hash) (*StateBatchJSON, error) { + const selectWithdrawalBatchStatement = ` SELECT - withdrawals.guid, withdrawals.from_address, withdrawals.to_address, - withdrawals.amount, withdrawals.tx_hash, withdrawals.data, - withdrawals.l1_token, withdrawals.l2_token, - l2_tokens.name, l2_tokens.symbol, l2_tokens.decimals, - l1_blocks.number, l1_blocks.timestamp, - l2_blocks.number, l2_blocks.timestamp - FROM withdrawals - INNER JOIN l1_blocks ON withdrawals.l1_block_hash=l1_blocks.hash - INNER JOIN l2_blocks ON withdrawals.l2_block_hash=l2_blocks.hash - INNER JOIN l2_tokens ON withdrawals.l2_token=l2_tokens.address - WHERE withdrawals.tx_hash = $1; + state_batches.index, state_batches.root, state_batches.size, state_batches.prev_total, state_batches.extra_data, state_batches.block_hash, + l1_blocks.number, l1_blocks.timestamp + FROM state_batches + INNER JOIN l1_blocks ON state_batches.block_hash = l1_blocks.hash + WHERE size + prev_total >= ( + SELECT + number + FROM + withdrawals + INNER JOIN l2_blocks ON withdrawals.block_hash = l2_blocks.hash where tx_hash=$1 + ) ORDER BY "index" LIMIT 1; ` - var withdrawal *WithdrawalJSON + var batch *StateBatchJSON err := txn(d.db, func(tx *sql.Tx) error { - row := tx.QueryRow(selectWithdrawalStatement, hash.String()) + row := tx.QueryRow(selectWithdrawalBatchStatement, hash.String()) if row.Err() != nil { return row.Err() } - var l2Token Token - if err := row.Scan( - &withdrawal.GUID, &withdrawal.FromAddress, &withdrawal.ToAddress, - &withdrawal.Amount, &withdrawal.TxHash, &withdrawal.Data, - &withdrawal.L1Token, &l2Token.Address, - &l2Token.Name, &l2Token.Symbol, &l2Token.Decimals, - &withdrawal.L1BlockNumber, &withdrawal.L1BlockTimestamp, - &withdrawal.L2BlockNumber, &withdrawal.L2BlockTimestamp, - ); err != nil { + var index, size, prevTotal, blockNumber, blockTimestamp uint64 + var root, blockHash string + var extraData []byte + err := row.Scan(&index, &root, &size, &prevTotal, &extraData, &blockHash, + &blockNumber, &blockTimestamp) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + batch = nil + return nil + } return err } - withdrawal.L2Token = &l2Token + + batch = &StateBatchJSON{ + Index: index, + Root: root, + Size: size, + PrevTotal: prevTotal, + ExtraData: extraData, + BlockHash: blockHash, + BlockNumber: blockNumber, + BlockTimestamp: blockTimestamp, + } return nil }) @@ -445,24 +473,26 @@ func (d *Database) GetWithdrawalStatus(hash common.Hash) (*WithdrawalJSON, error return nil, err } - return withdrawal, nil + return batch, nil } // GetWithdrawalsByAddress returns the list of Withdrawals indexed for the given // address paginated by the given params. -func (d *Database) GetWithdrawalsByAddress(address common.Address, page PaginationParam) (*PaginatedWithdrawals, error) { - const selectWithdrawalsStatement = ` +func (d *Database) GetWithdrawalsByAddress(address common.Address, page PaginationParam, state FinalizationState) (*PaginatedWithdrawals, error) { + selectWithdrawalsStatement := fmt.Sprintf(` SELECT withdrawals.guid, withdrawals.from_address, withdrawals.to_address, withdrawals.amount, withdrawals.tx_hash, withdrawals.data, withdrawals.l1_token, withdrawals.l2_token, l2_tokens.name, l2_tokens.symbol, l2_tokens.decimals, - l2_blocks.number, l2_blocks.timestamp + l2_blocks.number, l2_blocks.timestamp, withdrawals.br_withdrawal_hash, + withdrawals.br_withdrawal_finalized_tx_hash, withdrawals.br_withdrawal_finalized_log_index, + withdrawals.br_withdrawal_finalized_success FROM withdrawals - INNER JOIN l2_blocks ON withdrawals.l2_block_hash=l2_blocks.hash + INNER JOIN l2_blocks ON withdrawals.block_hash=l2_blocks.hash INNER JOIN l2_tokens ON withdrawals.l2_token=l2_tokens.address - WHERE withdrawals.from_address = $1 ORDER BY l2_blocks.timestamp LIMIT $2 OFFSET $3; - ` + WHERE withdrawals.from_address = $1 %s ORDER BY l2_blocks.timestamp LIMIT $2 OFFSET $3; + `, state.SQL()) var withdrawals []WithdrawalJSON err := txn(d.db, func(tx *sql.Tx) error { @@ -475,16 +505,34 @@ func (d *Database) GetWithdrawalsByAddress(address common.Address, page Paginati for rows.Next() { var withdrawal WithdrawalJSON var l2Token Token + var wdHash sql.NullString + var finTxHash sql.NullString + var finLogIndex sql.NullInt32 + var finSuccess sql.NullBool if err := rows.Scan( &withdrawal.GUID, &withdrawal.FromAddress, &withdrawal.ToAddress, &withdrawal.Amount, &withdrawal.TxHash, &withdrawal.Data, &withdrawal.L1Token, &l2Token.Address, &l2Token.Name, &l2Token.Symbol, &l2Token.Decimals, - &withdrawal.L2BlockNumber, &withdrawal.L2BlockTimestamp, + &withdrawal.BlockNumber, &withdrawal.BlockTimestamp, + &wdHash, &finTxHash, &finLogIndex, &finSuccess, ); err != nil { return err } withdrawal.L2Token = &l2Token + if wdHash.Valid { + withdrawal.BedrockWithdrawalHash = &wdHash.String + } + if finTxHash.Valid { + withdrawal.BedrockFinalizedTxHash = &finTxHash.String + } + if finLogIndex.Valid { + idx := int(finLogIndex.Int32) + withdrawal.BedrockFinalizedLogIndex = &idx + } + if finSuccess.Valid { + withdrawal.BedrockFinalizedSuccess = &finSuccess.Bool + } withdrawals = append(withdrawals, withdrawal) } @@ -495,11 +543,16 @@ func (d *Database) GetWithdrawalsByAddress(address common.Address, page Paginati return nil, err } + for i := range withdrawals { + batch, _ := d.GetWithdrawalBatch(common.HexToHash(withdrawals[i].TxHash)) + withdrawals[i].Batch = batch + } + const selectWithdrawalCountStatement = ` SELECT count(*) FROM withdrawals - INNER JOIN l2_blocks ON withdrawals.l2_block_hash=l2_blocks.hash + INNER JOIN l2_blocks ON withdrawals.block_hash=l2_blocks.hash INNER JOIN l2_tokens ON withdrawals.l2_token=l2_tokens.address WHERE withdrawals.from_address = $1; ` @@ -647,9 +700,9 @@ func (d *Database) GetIndexedL1BlockByHash(hash common.Hash) (*IndexedL1Block, e } const getAirdropQuery = ` -SELECT +SELECT address, voter_amount, multisig_signer_amount, gitcoin_amount, - active_bridged_amount, op_user_amount, op_repeat_user_amount, + active_bridged_amount, op_user_amount, op_repeat_user_amount, bonus_amount, total_amount FROM airdrops WHERE address = $1 @@ -681,3 +734,12 @@ func (d *Database) GetAirdrop(address common.Address) (*Airdrop, error) { } return airdrop, nil } + +func nullableHash(in *common.Hash) *string { + if in == nil { + return nil + } + + out := in.String() + return &out +} diff --git a/indexer/db/eth.go b/indexer/db/eth.go index 1cbb2d2443b7b..447ba892cf23b 100644 --- a/indexer/db/eth.go +++ b/indexer/db/eth.go @@ -1,24 +1,25 @@ package db -import "github.com/ethereum/go-ethereum/common" +import ( + "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum/go-ethereum/common" +) + +var ETHL1Address common.Address // ETHL1Token is a placeholder token for differentiating ETH transactions from // ERC20 transactions on L1. var ETHL1Token = &Token{ - Address: "0x0000000000000000000000000000000000000000", + Address: ETHL1Address.String(), Name: "Ethereum", Symbol: "ETH", Decimals: 18, } -// ETHL2Address is a placeholder address for differentiating ETH transactions -// from ERC20 transactions on L2. -var ETHL2Address = common.HexToAddress("0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000") - // ETHL2Token is a placeholder token for differentiating ETH transactions from // ERC20 transactions on L2. var ETHL2Token = &Token{ - Address: "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000", + Address: predeploys.LegacyERC20ETH, Name: "Ethereum", Symbol: "ETH", Decimals: 18, diff --git a/indexer/db/l1block.go b/indexer/db/l1block.go index 73dd33348b985..53b506d6ae005 100644 --- a/indexer/db/l1block.go +++ b/indexer/db/l1block.go @@ -6,12 +6,12 @@ import ( // IndexedL1Block contains the L1 block including the deposits in it. type IndexedL1Block struct { - Hash common.Hash - ParentHash common.Hash - Number uint64 - Timestamp uint64 - Deposits []Deposit - Withdrawals []Withdrawal + Hash common.Hash + ParentHash common.Hash + Number uint64 + Timestamp uint64 + Deposits []Deposit + FinalizedWithdrawals []FinalizedWithdrawal } // String returns the block hash for the indexed l1 block. @@ -25,7 +25,6 @@ type IndexedL2Block struct { ParentHash common.Hash Number uint64 Timestamp uint64 - Deposits []Deposit Withdrawals []Withdrawal } diff --git a/indexer/db/sql.go b/indexer/db/sql.go index 8a85abcb3f633..21c16af255eb9 100644 --- a/indexer/db/sql.go +++ b/indexer/db/sql.go @@ -28,10 +28,8 @@ CREATE TABLE IF NOT EXISTS deposits ( amount VARCHAR NOT NULL, data BYTEA NOT NULL, log_index INTEGER NOT NULL, - l1_block_hash VARCHAR NOT NULL REFERENCES l1_blocks(hash), - l2_block_hash VARCHAR REFERENCES l2_blocks(hash), - tx_hash VARCHAR NOT NULL, - failed BOOLEAN NOT NULL DEFAULT false + block_hash VARCHAR NOT NULL REFERENCES l1_blocks(hash), + tx_hash VARCHAR NOT NULL ) ` @@ -53,6 +51,20 @@ CREATE TABLE IF NOT EXISTS l2_tokens ( ) ` +const createStateBatchesTable = ` +CREATE TABLE IF NOT EXISTS state_batches ( + index INTEGER NOT NULL PRIMARY KEY, + root VARCHAR NOT NULL, + size INTEGER NOT NULL, + prev_total INTEGER NOT NULL, + extra_data BYTEA NOT NULL, + block_hash VARCHAR NOT NULL REFERENCES l1_blocks(hash) +); +CREATE INDEX IF NOT EXISTS state_batches_block_hash ON state_batches(block_hash); +CREATE INDEX IF NOT EXISTS state_batches_size ON state_batches(size); +CREATE INDEX IF NOT EXISTS state_batches_prev_total ON state_batches(prev_total); +` + const createWithdrawalsTable = ` CREATE TABLE IF NOT EXISTS withdrawals ( guid VARCHAR PRIMARY KEY NOT NULL, @@ -63,9 +75,9 @@ CREATE TABLE IF NOT EXISTS withdrawals ( amount VARCHAR NOT NULL, data BYTEA NOT NULL, log_index INTEGER NOT NULL, - l1_block_hash VARCHAR REFERENCES l1_blocks(hash), - l2_block_hash VARCHAR NOT NULL REFERENCES l2_blocks(hash), - tx_hash VARCHAR NOT NULL + block_hash VARCHAR NOT NULL REFERENCES l2_blocks(hash), + tx_hash VARCHAR NOT NULL, + state_batch INTEGER REFERENCES state_batches(index) ) ` @@ -110,15 +122,25 @@ CREATE TABLE IF NOT EXISTS airdrops ( ) ` +const updateWithdrawalsTable = ` +ALTER TABLE withdrawals ADD COLUMN IF NOT EXISTS br_withdrawal_hash VARCHAR NULL; +ALTER TABLE withdrawals ADD COLUMN IF NOT EXISTS br_withdrawal_finalized_tx_hash VARCHAR NULL; +ALTER TABLE withdrawals ADD COLUMN IF NOT EXISTS br_withdrawal_finalized_log_index INTEGER NULL; +ALTER TABLE withdrawals ADD COLUMN IF NOT EXISTS br_withdrawal_finalized_success BOOLEAN NULL; +CREATE INDEX IF NOT EXISTS withdrawals_br_withdrawal_hash ON withdrawals(br_withdrawal_hash); +` + var schema = []string{ createL1BlocksTable, createL2BlocksTable, createL1TokensTable, createL2TokensTable, + createStateBatchesTable, insertETHL1Token, insertETHL2Token, createDepositsTable, createWithdrawalsTable, createL1L2NumberIndex, createAirdropsTable, + updateWithdrawalsTable, } diff --git a/indexer/db/state_batch.go b/indexer/db/state_batch.go new file mode 100644 index 0000000000000..c8d820a4a1c2a --- /dev/null +++ b/indexer/db/state_batch.go @@ -0,0 +1,30 @@ +package db + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +// StateBatch is the state batch containing merkle root of the withdrawals +// periodically written to L1. +type StateBatch struct { + Index *big.Int + Root common.Hash + Size *big.Int + PrevTotal *big.Int + ExtraData []byte + BlockHash common.Hash +} + +// StateBatchJSON contains StateBatch data suitable for JSON serialization. +type StateBatchJSON struct { + Index uint64 `json:"index"` + Root string `json:"root"` + Size uint64 `json:"size"` + PrevTotal uint64 `json:"prevTotal"` + ExtraData []byte `json:"extraData"` + BlockHash string `json:"blockHash"` + BlockNumber uint64 `json:"blockNumber"` + BlockTimestamp uint64 `json:"blockTimestamp"` +} diff --git a/indexer/db/withdrawal.go b/indexer/db/withdrawal.go index da7fb1cbee799..2cc31963ac68b 100644 --- a/indexer/db/withdrawal.go +++ b/indexer/db/withdrawal.go @@ -17,6 +17,7 @@ type Withdrawal struct { Amount *big.Int Data []byte LogIndex uint + BedrockHash *common.Hash } // String returns the tx hash for the withdrawal. @@ -26,17 +27,57 @@ func (w Withdrawal) String() string { // WithdrawalJSON contains Withdrawal data suitable for JSON serialization. type WithdrawalJSON struct { - GUID string `json:"guid"` - FromAddress string `json:"from"` - ToAddress string `json:"to"` - L1Token string `json:"l1Token"` - L2Token *Token `json:"l2Token"` - Amount string `json:"amount"` - Data []byte `json:"data"` - LogIndex uint64 `json:"logIndex"` - L1BlockNumber uint64 `json:"l1BlockNumber"` - L1BlockTimestamp string `json:"l1BlockTimestamp"` - L2BlockNumber uint64 `json:"l2BlockNumber"` - L2BlockTimestamp string `json:"l2BlockTimestamp"` - TxHash string `json:"transactionHash"` + GUID string `json:"guid"` + FromAddress string `json:"from"` + ToAddress string `json:"to"` + L1Token string `json:"l1Token"` + L2Token *Token `json:"l2Token"` + Amount string `json:"amount"` + Data []byte `json:"data"` + LogIndex uint64 `json:"logIndex"` + BlockNumber uint64 `json:"blockNumber"` + BlockTimestamp string `json:"blockTimestamp"` + TxHash string `json:"transactionHash"` + Batch *StateBatchJSON `json:"batch"` + BedrockWithdrawalHash *string `json:"bedrockWithdrawalHash"` + BedrockFinalizedTxHash *string `json:"bedrockFinalizedTxHash"` + BedrockFinalizedLogIndex *int `json:"bedrockFinalizedLogIndex"` + BedrockFinalizedSuccess *bool `json:"bedrockFinalizedSuccess"` +} + +type FinalizationState int + +const ( + FinalizationStateAny FinalizationState = iota + FinalizationStateFinalized + FinalizationStateUnfinalized +) + +func ParseFinalizationState(in string) FinalizationState { + switch in { + case "true": + return FinalizationStateFinalized + case "false": + return FinalizationStateUnfinalized + default: + return FinalizationStateAny + } +} + +func (f FinalizationState) SQL() string { + switch f { + case FinalizationStateFinalized: + return "AND withdrawals.br_withdrawal_finalized_tx_hash IS NOT NULL" + case FinalizationStateUnfinalized: + return "AND withdrawals.br_withdrawal_finalized_tx_hash IS NULL" + } + + return "" +} + +type FinalizedWithdrawal struct { + WithdrawalHash common.Hash + TxHash common.Hash + Success bool + LogIndex uint } diff --git a/indexer/flags/flags.go b/indexer/flags/flags.go index 9818e0caab8c5..c14a24a4edd80 100644 --- a/indexer/flags/flags.go +++ b/indexer/flags/flags.go @@ -46,11 +46,11 @@ var ( Required: true, EnvVar: prefixEnvVar("L2_ETH_RPC"), } - L2GenesisBlockHashFlag = cli.StringFlag{ - Name: "l2-genesis-block-hash", - Usage: "Genesis block hash of the L2 chain", + L1AddressManagerAddressFlag = cli.StringFlag{ + Name: "l1-address-manager-address", + Usage: "Address of the L1 address manager", Required: true, - EnvVar: prefixEnvVar("L2_GENESIS_BLOCK_HASH"), + EnvVar: prefixEnvVar("L1_ADDRESS_MANAGER_ADDRESS"), } DBHostFlag = cli.StringFlag{ Name: "db-host", @@ -83,6 +83,23 @@ var ( EnvVar: prefixEnvVar("DB_NAME"), } + /* Bedrock Flags */ + BedrockFlag = cli.BoolFlag{ + Name: "bedrock", + Usage: "Whether or not this indexer should operate in Bedrock mode", + EnvVar: prefixEnvVar("BEDROCK"), + } + BedrockL1StandardBridgeAddress = cli.BoolFlag{ + Name: "bedrock.l1-standard-bridge-address", + Usage: "Address of the L1 standard bridge", + EnvVar: prefixEnvVar("BEDROCK_L1_STANDARD_BRIDGE"), + } + BedrockOptimismPortalAddress = cli.BoolFlag{ + Name: "bedrock.portal-address", + Usage: "Address of the portal", + EnvVar: prefixEnvVar("BEDROCK_OPTIMISM_PORTAL"), + } + /* Optional Flags */ DisableIndexer = cli.BoolFlag{ @@ -120,18 +137,12 @@ var ( Value: 50 * time.Millisecond, EnvVar: prefixEnvVar("SENTRY_TRACE_RATE"), } - StartBlockNumberFlag = cli.Uint64Flag{ + L1StartBlockNumberFlag = cli.Uint64Flag{ Name: "start-block-number", Usage: "The block number to start indexing from. Must be use together with start block hash", Value: 0, EnvVar: prefixEnvVar("START_BLOCK_NUMBER"), } - StartBlockHashFlag = cli.StringFlag{ - Name: "start-block-hash", - Usage: "The block hash to start indexing from. Must be use together with start block number", - Value: "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", - EnvVar: prefixEnvVar("START_BLOCK_HASH"), - } ConfDepthFlag = cli.Uint64Flag{ Name: "conf-depth", Usage: "The number of confirmations after which headers are considered confirmed", @@ -181,7 +192,7 @@ var requiredFlags = []cli.Flag{ ChainIDFlag, L1EthRPCFlag, L2EthRPCFlag, - L2GenesisBlockHashFlag, + L1AddressManagerAddressFlag, DBHostFlag, DBPortFlag, DBUserFlag, @@ -190,6 +201,9 @@ var requiredFlags = []cli.Flag{ } var optionalFlags = []cli.Flag{ + BedrockFlag, + BedrockL1StandardBridgeAddress, + BedrockOptimismPortalAddress, DisableIndexer, LogLevelFlag, LogTerminalFlag, @@ -198,8 +212,7 @@ var optionalFlags = []cli.Flag{ SentryTraceRateFlag, ConfDepthFlag, MaxHeaderBatchSizeFlag, - StartBlockNumberFlag, - StartBlockHashFlag, + L1StartBlockNumberFlag, RESTHostnameFlag, RESTPortFlag, MetricsServerEnableFlag, diff --git a/indexer/indexer.go b/indexer/indexer.go index eb9269b7aad67..e07181e8e6b6c 100644 --- a/indexer/indexer.go +++ b/indexer/indexer.go @@ -11,6 +11,7 @@ import ( "time" "github.com/ethereum-optimism/optimism/indexer/services" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum-optimism/optimism/indexer/metrics" "github.com/ethereum-optimism/optimism/indexer/server" @@ -22,7 +23,6 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" - sentry "github.com/getsentry/sentry-go" "github.com/gorilla/mux" "github.com/urfave/cli" ) @@ -44,15 +44,9 @@ func Main(gitVersion string) func(ctx *cli.Context) error { return err } - // The call to defer is done here so that any errors logged from - // this point on are posted to Sentry before exiting. - if cfg.SentryEnable { - defer sentry.Flush(2 * time.Second) - } - log.Info("Initializing indexer") - indexer, err := NewIndexer(cfg, gitVersion) + indexer, err := NewIndexer(cfg) if err != nil { log.Error("Unable to create indexer", "error", err) return err @@ -87,32 +81,18 @@ type Indexer struct { router *mux.Router metrics *metrics.Metrics + db *database.Database + server *http.Server } // NewIndexer initializes the Indexer, gathering any resources // that will be needed by the TxIndexer and StateIndexer // sub-services. -func NewIndexer(cfg Config, gitVersion string) (*Indexer, error) { +func NewIndexer(cfg Config) (*Indexer, error) { ctx := context.Background() - // Set up our logging. If Sentry is enabled, we will use our custom - // log handler that logs to stdout and forwards any error messages to - // Sentry for collection. Otherwise, logs will only be posted to stdout. var logHandler log.Handler - if cfg.SentryEnable { - err := sentry.Init(sentry.ClientOptions{ - Dsn: cfg.SentryDsn, - Environment: cfg.EthNetworkName, - Release: "indexer@" + gitVersion, - TracesSampleRate: traceRateToFloat64(cfg.SentryTraceRate), - Debug: false, - }) - if err != nil { - return nil, err - } - - logHandler = SentryStreamHandler(os.Stdout, log.JSONFormat()) - } else if cfg.LogTerminal { + if cfg.LogTerminal { logHandler = log.StreamHandler(os.Stdout, log.TerminalFormat(true)) } else { logHandler = log.StreamHandler(os.Stdout, log.JSONFormat()) @@ -149,8 +129,11 @@ func NewIndexer(cfg Config, gitVersion string) (*Indexer, error) { log.Info("metrics server enabled", "host", cfg.MetricsHostname, "port", cfg.MetricsPort) } - dsn := fmt.Sprintf("host=%s port=%d user=%s dbname=%s sslmode=disable", - cfg.DBHost, cfg.DBPort, cfg.DBUser, cfg.DBName) + dsn := fmt.Sprintf("host=%s port=%d dbname=%s sslmode=disable", + cfg.DBHost, cfg.DBPort, cfg.DBName) + if cfg.DBUser != "" { + dsn += fmt.Sprintf(" user=%s", cfg.DBUser) + } if cfg.DBPassword != "" { dsn += fmt.Sprintf(" password=%s", cfg.DBPassword) } @@ -159,17 +142,32 @@ func NewIndexer(cfg Config, gitVersion string) (*Indexer, error) { return nil, err } + var addrManager services.AddressManager + if cfg.Bedrock { + addrManager, err = services.NewBedrockAddresses( + l1Client, + cfg.BedrockL1StandardBridgeAddress, + cfg.BedrockOptimismPortalAddress, + ) + } else { + addrManager, err = services.NewLegacyAddresses(l1Client, common.HexToAddress(cfg.L1AddressManagerAddress)) + } + if err != nil { + return nil, err + } + l1IndexingService, err := l1.NewService(l1.ServiceConfig{ Context: ctx, Metrics: m, L1Client: l1Client, RawL1Client: rawl1Client, - ChainID: big.NewInt(cfg.ChainID), + ChainID: new(big.Int).SetUint64(cfg.ChainID), + AddressManager: addrManager, DB: db, ConfDepth: cfg.ConfDepth, MaxHeaderBatchSize: cfg.MaxHeaderBatchSize, - StartBlockNumber: cfg.StartBlockNumber, - StartBlockHash: cfg.StartBlockHash, + StartBlockNumber: cfg.L1StartBlockNumber, + Bedrock: cfg.Bedrock, }) if err != nil { return nil, err @@ -184,7 +182,7 @@ func NewIndexer(cfg Config, gitVersion string) (*Indexer, error) { ConfDepth: cfg.ConfDepth, MaxHeaderBatchSize: cfg.MaxHeaderBatchSize, StartBlockNumber: uint64(0), - StartBlockHash: cfg.L2GenesisBlockHash, + Bedrock: cfg.Bedrock, }) if err != nil { return nil, err @@ -200,6 +198,7 @@ func NewIndexer(cfg Config, gitVersion string) (*Indexer, error) { airdropService: services.NewAirdrop(db, m), router: mux.NewRouter(), metrics: m, + db: db, }, nil } @@ -212,7 +211,7 @@ func (b *Indexer) Serve() error { b.router.HandleFunc("/v1/l1/status", b.l1IndexingService.GetIndexerStatus).Methods("GET") b.router.HandleFunc("/v1/l2/status", b.l2IndexingService.GetIndexerStatus).Methods("GET") b.router.HandleFunc("/v1/deposits/0x{address:[a-fA-F0-9]{40}}", b.l1IndexingService.GetDeposits).Methods("GET") - b.router.HandleFunc("/v1/withdrawal/0x{hash:[a-fA-F0-9]{64}}", b.l2IndexingService.GetWithdrawalStatus).Methods("GET") + b.router.HandleFunc("/v1/withdrawal/0x{hash:[a-fA-F0-9]{64}}", b.l2IndexingService.GetWithdrawalBatch).Methods("GET") b.router.HandleFunc("/v1/withdrawals/0x{address:[a-fA-F0-9]{40}}", b.l2IndexingService.GetWithdrawals).Methods("GET") b.router.HandleFunc("/v1/airdrops/0x{address:[a-fA-F0-9]{40}}", b.airdropService.GetAirdrop) b.router.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { @@ -228,8 +227,27 @@ func (b *Indexer) Serve() error { port := strconv.FormatUint(b.cfg.RESTPort, 10) addr := net.JoinHostPort(b.cfg.RESTHostname, port) - log.Info("indexer REST server listening on", "addr", addr) - return http.ListenAndServe(addr, middleware(c.Handler(b.router))) + b.server = &http.Server{ + Addr: addr, + Handler: middleware(c.Handler(b.router)), + } + + errCh := make(chan error, 1) + + go func() { + errCh <- b.server.ListenAndServe() + }() + + // Capture server startup errors + <-time.After(10 * time.Millisecond) + + select { + case err := <-errCh: + return err + default: + log.Info("indexer REST server listening on", "addr", addr) + return nil + } } // Start starts the starts the indexing service on L1 and L2 chains and also @@ -253,6 +271,14 @@ func (b *Indexer) Start() error { // Stop stops the indexing service on L1 and L2 chains. func (b *Indexer) Stop() { + b.db.Close() + + if b.server != nil { + // background context here so it waits for + // conns to close + _ = b.server.Shutdown(context.Background()) + } + if !b.cfg.DisableIndexer { b.l1IndexingService.Stop() b.l2IndexingService.Stop() @@ -274,14 +300,3 @@ func dialEthClientWithTimeout(ctx context.Context, url string) ( } return ethclient.NewClient(c), c, nil } - -// traceRateToFloat64 converts a time.Duration into a valid float64 for the -// Sentry client. The client only accepts values between 0.0 and 1.0, so this -// method clamps anything greater than 1 second to 1.0. -func traceRateToFloat64(rate time.Duration) float64 { - rate64 := float64(rate) / float64(time.Second) - if rate64 > 1.0 { - rate64 = 1.0 - } - return rate64 -} diff --git a/indexer/integration_tests/bedrock_test.go b/indexer/integration_tests/bedrock_test.go new file mode 100644 index 0000000000000..5e3020f1bca29 --- /dev/null +++ b/indexer/integration_tests/bedrock_test.go @@ -0,0 +1,304 @@ +package integration_tests + +import ( + "context" + "database/sql" + "encoding/json" + "fmt" + "math/big" + "net/http" + "os" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/indexer" + "github.com/ethereum-optimism/optimism/indexer/db" + "github.com/ethereum-optimism/optimism/indexer/services/l1" + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/withdrawals" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" + + _ "github.com/lib/pq" +) + +func TestBedrockIndexer(t *testing.T) { + dbParams := createTestDB(t) + + cfg := op_e2e.DefaultSystemConfig(t) + cfg.DeployConfig.FinalizationPeriodSeconds = 2 + sys, err := cfg.Start() + require.NoError(t, err) + defer sys.Close() + + l1Client := sys.Clients["l1"] + l2Client := sys.Clients["sequencer"] + fromAddr := cfg.Secrets.Addresses().Alice + + // wait a couple of blocks + require.NoError(t, e2eutils.WaitBlock(e2eutils.TimeoutCtx(t, 30*time.Second), l2Client, 10)) + + l1SB, err := bindings.NewL1StandardBridge(predeploys.DevL1StandardBridgeAddr, l1Client) + require.NoError(t, err) + l2SB, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, l2Client) + require.NoError(t, err) + portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) + require.NoError(t, err) + l1Opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Alice, cfg.L1ChainIDBig()) + require.NoError(t, err) + l2Opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Alice, cfg.L2ChainIDBig()) + require.NoError(t, err) + + idxrCfg := indexer.Config{ + ChainID: cfg.DeployConfig.L1ChainID, + L1EthRpc: sys.Nodes["l1"].HTTPEndpoint(), + L2EthRpc: sys.Nodes["sequencer"].HTTPEndpoint(), + PollInterval: time.Second, + DBHost: dbParams.Host, + DBPort: dbParams.Port, + DBUser: dbParams.User, + DBPassword: dbParams.Password, + DBName: dbParams.Name, + LogLevel: "info", + LogTerminal: true, + L1StartBlockNumber: 0, + ConfDepth: 1, + MaxHeaderBatchSize: 2, + RESTHostname: "127.0.0.1", + RESTPort: 7980, + DisableIndexer: false, + Bedrock: true, + BedrockL1StandardBridgeAddress: predeploys.DevL1StandardBridgeAddr, + BedrockOptimismPortalAddress: predeploys.DevOptimismPortalAddr, + } + idxr, err := indexer.NewIndexer(idxrCfg) + require.NoError(t, err) + + errCh := make(chan error, 1) + go func() { + errCh <- idxr.Start() + }() + + t.Cleanup(func() { + idxr.Stop() + require.NoError(t, <-errCh) + }) + + makeURL := func(path string) string { + return fmt.Sprintf("http://%s:%d/%s", idxrCfg.RESTHostname, idxrCfg.RESTPort, path) + } + + t.Run("deposit ETH", func(t *testing.T) { + l1Opts.Value = big.NewInt(params.Ether) + depTx, err := l1SB.DepositETH(l1Opts, 200_000, nil) + require.NoError(t, err) + depReceipt, err := e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, 10*time.Second), l1Client, depTx.Hash()) + require.NoError(t, err) + require.Greaterf(t, len(depReceipt.Logs), 0, "must have logs") + var l2Hash common.Hash + for _, eLog := range depReceipt.Logs { + if len(eLog.Topics) == 0 || eLog.Topics[0] != derive.DepositEventABIHash { + continue + } + + depLog, err := derive.UnmarshalDepositLogEvent(eLog) + require.NoError(t, err) + tx := types.NewTx(depLog) + l2Hash = tx.Hash() + } + require.NotEqual(t, common.Hash{}, l2Hash) + _, err = e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, 15*time.Second), l2Client, l2Hash) + require.NoError(t, err) + + // Poll for indexer deposit + var depPage *db.PaginatedDeposits + require.NoError(t, e2eutils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) { + res := new(db.PaginatedDeposits) + err := getJSON(makeURL(fmt.Sprintf("v1/deposits/%s", fromAddr)), res) + if err != nil { + return false, err + } + + if len(res.Deposits) == 0 { + return false, nil + } + + depPage = res + return true, nil + })) + + // Make sure deposit is what we expect + require.Equal(t, 1, len(depPage.Deposits)) + deposit := depPage.Deposits[0] + require.Equal(t, big.NewInt(params.Ether).String(), deposit.Amount) + require.Equal(t, depTx.Hash().String(), deposit.TxHash) + require.Equal(t, depReceipt.BlockNumber.Uint64(), deposit.BlockNumber) + require.Equal(t, fromAddr.String(), deposit.FromAddress) + require.Equal(t, fromAddr.String(), deposit.ToAddress) + require.EqualValues(t, db.ETHL1Token, deposit.L1Token) + require.Equal(t, l1.ZeroAddress.String(), deposit.L2Token) + require.NotEmpty(t, deposit.GUID) + + // Perform withdrawal through bridge + l2Opts.Value = big.NewInt(0.5 * params.Ether) + wdTx, err := l2SB.Withdraw(l2Opts, predeploys.LegacyERC20ETHAddr, big.NewInt(0.5*params.Ether), 0, nil) + require.NoError(t, err) + wdReceipt, err := e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, 30*time.Second), l2Client, wdTx.Hash()) + require.NoError(t, err) + + var wdPage *db.PaginatedWithdrawals + require.NoError(t, e2eutils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) { + res := new(db.PaginatedWithdrawals) + err := getJSON(makeURL(fmt.Sprintf("v1/withdrawals/%s", fromAddr)), res) + if err != nil { + return false, err + } + + if len(res.Withdrawals) == 0 { + return false, nil + } + + wdPage = res + return true, nil + })) + + require.Equal(t, 1, len(wdPage.Withdrawals)) + withdrawal := wdPage.Withdrawals[0] + require.Nil(t, withdrawal.BedrockFinalizedTxHash) + require.Equal(t, big.NewInt(0.5*params.Ether).String(), withdrawal.Amount) + require.Equal(t, wdTx.Hash().String(), withdrawal.TxHash) + require.Equal(t, wdReceipt.BlockNumber.Uint64(), withdrawal.BlockNumber) + // use fromaddr twice here because the user is withdrawing + // to themselves + require.Equal(t, fromAddr.String(), withdrawal.FromAddress) + require.Equal(t, fromAddr.String(), withdrawal.ToAddress) + require.EqualValues(t, l1.ZeroAddress.String(), withdrawal.L1Token) + require.Equal(t, db.ETHL2Token, withdrawal.L2Token) + require.NotEmpty(t, withdrawal.GUID) + + finBlockNum, err := withdrawals.WaitForFinalizationPeriod( + e2eutils.TimeoutCtx(t, time.Minute), + l1Client, + predeploys.DevOptimismPortalAddr, + wdReceipt.BlockNumber, + ) + require.NoError(t, err) + finHeader, err := l2Client.HeaderByNumber(context.Background(), big.NewInt(int64(finBlockNum))) + require.NoError(t, err) + + rpcClient, err := rpc.Dial(sys.Nodes["sequencer"].HTTPEndpoint()) + require.NoError(t, err) + proofClient := withdrawals.NewClient(rpcClient) + wParams, err := withdrawals.FinalizeWithdrawalParameters(context.Background(), proofClient, wdTx.Hash(), finHeader) + require.NoError(t, err) + + l1Opts.Value = big.NewInt(0) + finTx, err := portal.FinalizeWithdrawalTransaction( + l1Opts, + bindings.TypesWithdrawalTransaction{ + Nonce: wParams.Nonce, + Sender: wParams.Sender, + Target: wParams.Target, + Value: wParams.Value, + GasLimit: wParams.GasLimit, + Data: wParams.Data, + }, + wParams.BlockNumber, + wParams.OutputRootProof, + wParams.WithdrawalProof, + ) + require.NoError(t, err) + + finReceipt, err := e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, time.Minute), l1Client, finTx.Hash()) + require.NoError(t, err) + + wdPage = nil + require.NoError(t, e2eutils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) { + res := new(db.PaginatedWithdrawals) + err := getJSON(makeURL(fmt.Sprintf("v1/withdrawals/%s", fromAddr)), res) + if err != nil { + return false, err + } + + if res.Withdrawals[0].BedrockFinalizedTxHash == nil { + return false, nil + } + + wdPage = res + return true, nil + })) + + wd := wdPage.Withdrawals[0] + require.Equal(t, finReceipt.TxHash.String(), *wd.BedrockFinalizedTxHash) + require.True(t, *wd.BedrockFinalizedSuccess) + + wdPage = new(db.PaginatedWithdrawals) + err = getJSON(makeURL(fmt.Sprintf("v1/withdrawals/%s?finalized=false", fromAddr)), wdPage) + require.NoError(t, err) + require.Equal(t, 0, len(wdPage.Withdrawals)) + }) +} + +type testDBParams struct { + Host string + Port uint64 + User string + Password string + Name string +} + +func createTestDB(t *testing.T) *testDBParams { + user := os.Getenv("DB_USER") + name := fmt.Sprintf("indexer_test_%d", time.Now().Unix()) + + dsn := "postgres://" + if user != "" { + dsn += user + dsn += "@" + } + dsn += "localhost:5432?sslmode=disable" + pg, err := sql.Open( + "postgres", + dsn, + ) + require.NoError(t, err) + + _, err = pg.Exec("CREATE DATABASE " + name) + require.NoError(t, err) + + t.Cleanup(func() { + _, err = pg.Exec("DROP DATABASE " + name) + require.NoError(t, err) + pg.Close() + }) + + return &testDBParams{ + Host: "localhost", + Port: 5432, + Name: name, + User: user, + } +} + +func getJSON(url string, out interface{}) error { + res, err := http.Get(url) + if err != nil { + return err + } + + if res.StatusCode != 200 { + return fmt.Errorf("non-200 status code %d", res.StatusCode) + } + + defer res.Body.Close() + dec := json.NewDecoder(res.Body) + return dec.Decode(out) +} diff --git a/indexer/metrics/metrics.go b/indexer/metrics/metrics.go index 2a0e895ee9472..6027d13fd91e5 100644 --- a/indexer/metrics/metrics.go +++ b/indexer/metrics/metrics.go @@ -21,6 +21,8 @@ type Metrics struct { WithdrawalsCount *prometheus.CounterVec + StateBatchesCount prometheus.Counter + L1CatchingUp prometheus.Gauge L2CatchingUp prometheus.Gauge @@ -72,6 +74,12 @@ func NewMetrics(monitoredTokens map[string]string) *Metrics { "symbol", }), + StateBatchesCount: promauto.NewCounter(prometheus.CounterOpts{ + Name: "state_batches_count", + Help: "The number of state batches indexed.", + Namespace: metricsNamespace, + }), + L1CatchingUp: promauto.NewGauge(prometheus.GaugeOpts{ Name: "l1_catching_up", Help: "Whether or not L1 is far behind the chain tip.", @@ -160,6 +168,10 @@ func (m *Metrics) RecordWithdrawal(addr common.Address) { m.WithdrawalsCount.WithLabelValues(sym).Inc() } +func (m *Metrics) RecordStateBatches(count int) { + m.StateBatchesCount.Add(float64(count)) +} + func (m *Metrics) SetL1CatchingUp(state bool) { var catchingUp float64 if state { diff --git a/indexer/sentry_log.go b/indexer/sentry_log.go deleted file mode 100644 index 484b727dc270e..0000000000000 --- a/indexer/sentry_log.go +++ /dev/null @@ -1,38 +0,0 @@ -package indexer - -import ( - "errors" - "io" - - "github.com/ethereum/go-ethereum/log" - "github.com/getsentry/sentry-go" -) - -var jsonFmt = log.JSONFormat() - -// SentryStreamHandler creates a log.Handler that behaves similarly to -// log.StreamHandler, however it writes any log with severity greater than or -// equal to log.LvlError to Sentry. In that case, the passed log.Record is -// encoded using JSON rather than the default terminal output, so that it can be -// captured for debugging in the Sentry dashboard. -func SentryStreamHandler(wr io.Writer, fmtr log.Format) log.Handler { - h := log.FuncHandler(func(r *log.Record) error { - _, err := wr.Write(fmtr.Format(r)) - // If this record's severity is log.LvlError or higher, - // serialize the record using JSON and write it to Sentry. We - // also capture the error message separately so that it's easy - // to parse what the error is in the dashboard. - // - // NOTE: The log.Lvl* constants are defined in reverse order of - // their severity, i.e. zero (log.LvlCrit) is the highest - // severity. - if r.Lvl <= log.LvlError { - sentry.WithScope(func(scope *sentry.Scope) { - scope.SetExtra("context", jsonFmt.Format(r)) - sentry.CaptureException(errors.New(r.Msg)) - }) - } - return err - }) - return log.LazyHandler(log.SyncHandler(h)) -} diff --git a/indexer/services/addresses.go b/indexer/services/addresses.go new file mode 100644 index 0000000000000..40908b1004364 --- /dev/null +++ b/indexer/services/addresses.go @@ -0,0 +1,105 @@ +package services + +import ( + "github.com/ethereum-optimism/optimism/indexer/bindings/legacy/scc" + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +type AddressManager interface { + L1StandardBridge() (common.Address, *bindings.L1StandardBridge) + StateCommitmentChain() (common.Address, *scc.StateCommitmentChain) + OptimismPortal() (common.Address, *bindings.OptimismPortal) +} + +type LegacyAddresses struct { + l1SB *bindings.L1StandardBridge + l1SBAddr common.Address + scc *scc.StateCommitmentChain + sccAddr common.Address +} + +var _ AddressManager = (*LegacyAddresses)(nil) + +func NewLegacyAddresses(client bind.ContractBackend, addrMgrAddr common.Address) (AddressManager, error) { + mgr, err := bindings.NewAddressManager(addrMgrAddr, client) + if err != nil { + return nil, err + } + + l1SBAddr, err := mgr.GetAddress(nil, "Proxy__OVM_L1StandardBridge") + if err != nil { + return nil, err + } + sccAddr, err := mgr.GetAddress(nil, "StateCommitmentChain") + if err != nil { + return nil, err + } + l1SB, err := bindings.NewL1StandardBridge(l1SBAddr, client) + if err != nil { + return nil, err + } + sccContract, err := scc.NewStateCommitmentChain(sccAddr, client) + if err != nil { + return nil, err + } + + return &LegacyAddresses{ + l1SB: l1SB, + l1SBAddr: l1SBAddr, + scc: sccContract, + sccAddr: sccAddr, + }, nil +} + +func (a *LegacyAddresses) L1StandardBridge() (common.Address, *bindings.L1StandardBridge) { + return a.l1SBAddr, a.l1SB +} + +func (a *LegacyAddresses) StateCommitmentChain() (common.Address, *scc.StateCommitmentChain) { + return a.sccAddr, a.scc +} + +func (a *LegacyAddresses) OptimismPortal() (common.Address, *bindings.OptimismPortal) { + panic("OptimismPortal not configured on legacy networks - this is a programmer error") +} + +type BedrockAddresses struct { + l1SB *bindings.L1StandardBridge + l1SBAddr common.Address + portal *bindings.OptimismPortal + portalAddr common.Address +} + +var _ AddressManager = (*BedrockAddresses)(nil) + +func NewBedrockAddresses(client bind.ContractBackend, l1SBAddr, portalAddr common.Address) (AddressManager, error) { + l1SB, err := bindings.NewL1StandardBridge(l1SBAddr, client) + if err != nil { + return nil, err + } + portal, err := bindings.NewOptimismPortal(portalAddr, client) + if err != nil { + return nil, err + } + + return &BedrockAddresses{ + l1SB: l1SB, + l1SBAddr: l1SBAddr, + portal: portal, + portalAddr: portalAddr, + }, nil +} + +func (b *BedrockAddresses) L1StandardBridge() (common.Address, *bindings.L1StandardBridge) { + return b.l1SBAddr, b.l1SB +} + +func (b *BedrockAddresses) StateCommitmentChain() (common.Address, *scc.StateCommitmentChain) { + panic("SCC not configured on legacy networks - this is a programmer error") +} + +func (b *BedrockAddresses) OptimismPortal() (common.Address, *bindings.OptimismPortal) { + return b.portalAddr, b.portal +} diff --git a/indexer/services/l1/bridge/bridge.go b/indexer/services/l1/bridge/bridge.go index 69df64c17a7c4..1ab8813bfcb0e 100644 --- a/indexer/services/l1/bridge/bridge.go +++ b/indexer/services/l1/bridge/bridge.go @@ -5,93 +5,85 @@ import ( "errors" "math/big" + "github.com/ethereum-optimism/optimism/indexer/bindings/legacy/scc" "github.com/ethereum-optimism/optimism/indexer/db" + "github.com/ethereum-optimism/optimism/indexer/services" "github.com/ethereum-optimism/optimism/op-bindings/bindings" - "github.com/ethereum-optimism/optimism/op-bindings/predeploys" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) +// DepositsMap is a collection of deposit objects keyed +// on block hashes. type DepositsMap map[common.Hash][]db.Deposit -type WithdrawalsMap map[common.Hash][]db.Withdrawal // Finalizations + +// WithdrawalsMap is a collection of withdrawal objects keyed +// on block hashes. +type InitiatedWithdrawalMap map[common.Hash][]db.Withdrawal + +// FinalizedWithdrawalsMap is a collection of finalized withdrawal +// objected keyed on block hashes. +type FinalizedWithdrawalsMap map[common.Hash][]db.FinalizedWithdrawal type Bridge interface { Address() common.Address - GetDepositsByBlockRange(uint64, uint64) (DepositsMap, error) - GetWithdrawalsByBlockRange(uint64, uint64) (WithdrawalsMap, error) + GetDepositsByBlockRange(context.Context, uint64, uint64) (DepositsMap, error) String() string } type implConfig struct { name string impl string - addr string -} - -var defaultBridgeCfgs = map[uint64][]*implConfig{ - // Devnet - 900: { - {"Standard", "StandardBridge", predeploys.DevL1StandardBridge}, - {"ETH", "ETHBridge", predeploys.DevL1StandardBridge}, - }, - // Goerli - 5: { - {"Standard", "StandardBridge", "0xFf94B6C486350aD92561Ba09bad3a59df764Da92"}, - {"ETH", "ETHBridge", "0xFf94B6C486350aD92561Ba09bad3a59df764Da92"}, - }, + addr common.Address } var customBridgeCfgs = map[uint64][]*implConfig{ // Mainnet 1: { - {"BitBTC", "StandardBridge", "0xaBA2c5F108F7E820C049D5Af70B16ac266c8f128"}, - {"DAI", "StandardBridge", "0x10E6593CDda8c58a1d0f14C5164B376352a55f2F"}, + {"BitBTC", "StandardBridge", common.HexToAddress("0xaBA2c5F108F7E820C049D5Af70B16ac266c8f128")}, + {"DAI", "StandardBridge", common.HexToAddress("0x10E6593CDda8c58a1d0f14C5164B376352a55f2F")}, + {"wstETH", "StandardBridge", common.HexToAddress("0x76943C0D61395d8F2edF9060e1533529cAe05dE6")}, }, // Kovan 42: { - {"BitBTC", "StandardBridge", "0x0b651A42F32069d62d5ECf4f2a7e5Bd3E9438746"}, - {"USX", "StandardBridge", "0x40E862341b2416345F02c41Ac70df08525150dC7"}, - {"DAI", "StandardBridge", "0xb415e822C4983ecD6B1c1596e8a5f976cf6CD9e3"}, + {"BitBTC", "StandardBridge", common.HexToAddress("0x0b651A42F32069d62d5ECf4f2a7e5Bd3E9438746")}, + {"USX", "StandardBridge", common.HexToAddress("0x40E862341b2416345F02c41Ac70df08525150dC7")}, + {"DAI", "StandardBridge", common.HexToAddress("0xb415e822C4983ecD6B1c1596e8a5f976cf6CD9e3")}, + {"wstETH", "StandardBridge", common.HexToAddress("0x65321bf24210b81500230dCEce14Faa70a9f50a7")}, }, } -func BridgesByChainID(chainID *big.Int, client bind.ContractBackend, ctx context.Context) (map[string]Bridge, error) { - allCfgs := make([]*implConfig, 0) - allCfgs = append(allCfgs, defaultBridgeCfgs[chainID.Uint64()]...) +func BridgesByChainID(chainID *big.Int, client bind.ContractBackend, addrs services.AddressManager) (map[string]Bridge, error) { + l1SBAddr, _ := addrs.L1StandardBridge() + allCfgs := []*implConfig{ + {"Standard", "StandardBridge", l1SBAddr}, + {"ETH", "ETHBridge", l1SBAddr}, + } allCfgs = append(allCfgs, customBridgeCfgs[chainID.Uint64()]...) bridges := make(map[string]Bridge) for _, bridge := range allCfgs { switch bridge.impl { case "StandardBridge": - l1StandardBridgeAddress := common.HexToAddress(bridge.addr) - l1StandardBridgeFilter, err := bindings.NewL1StandardBridgeFilterer(l1StandardBridgeAddress, client) + l1SB, err := bindings.NewL1StandardBridge(bridge.addr, client) if err != nil { return nil, err } - standardBridge := &StandardBridge{ name: bridge.name, - ctx: ctx, - address: l1StandardBridgeAddress, - client: client, - filterer: l1StandardBridgeFilter, + address: bridge.addr, + contract: l1SB, } bridges[bridge.name] = standardBridge case "ETHBridge": - l1StandardBridgeAddress := common.HexToAddress(bridge.addr) - l1EthBridgeFilter, err := bindings.NewL1StandardBridgeFilterer(l1StandardBridgeAddress, client) + l1SB, err := bindings.NewL1StandardBridge(bridge.addr, client) if err != nil { return nil, err } - ethBridge := &EthBridge{ name: bridge.name, - ctx: ctx, - address: l1StandardBridgeAddress, - client: client, - filterer: l1EthBridgeFilter, + address: bridge.addr, + contract: l1SB, } bridges[bridge.name] = ethBridge default: @@ -100,3 +92,12 @@ func BridgesByChainID(chainID *big.Int, client bind.ContractBackend, ctx context } return bridges, nil } + +func StateCommitmentChainScanner(client bind.ContractFilterer, addrs services.AddressManager) (*scc.StateCommitmentChainFilterer, error) { + sccAddr, _ := addrs.StateCommitmentChain() + filter, err := scc.NewStateCommitmentChainFilterer(sccAddr, client) + if err != nil { + return nil, err + } + return filter, nil +} diff --git a/indexer/services/l1/bridge/bridge.go.orig b/indexer/services/l1/bridge/bridge.go.orig new file mode 100644 index 0000000000000..f9a4904aa7bd7 --- /dev/null +++ b/indexer/services/l1/bridge/bridge.go.orig @@ -0,0 +1,107 @@ +package bridge + +import ( + "context" + "errors" + "math/big" + + "github.com/ethereum-optimism/optimism/indexer/bindings/legacy/scc" + "github.com/ethereum-optimism/optimism/indexer/db" + "github.com/ethereum-optimism/optimism/indexer/services" + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +// DepositsMap is a collection of deposit objects keyed +// on block hashes. +type DepositsMap map[common.Hash][]db.Deposit +<<<<<<< HEAD + +// WithdrawalsMap is a collection of withdrawal objects keyed +// on block hashes. +type WithdrawalsMap map[common.Hash][]db.Withdrawal + +// FinalizedWithdrawalsMap is a collection of finalized withdrawal +// objected keyed on block hashes. +======= +type InitiatedWithdrawalMap map[common.Hash][]db.Withdrawal +>>>>>>> 22c039efc (indexer: Upgrade L1 services) +type FinalizedWithdrawalsMap map[common.Hash][]db.FinalizedWithdrawal + +type Bridge interface { + Address() common.Address + GetDepositsByBlockRange(context.Context, uint64, uint64) (DepositsMap, error) + String() string +} + +type implConfig struct { + name string + impl string + addr common.Address +} + +var customBridgeCfgs = map[uint64][]*implConfig{ + // Mainnet + 1: { + {"BitBTC", "StandardBridge", common.HexToAddress("0xaBA2c5F108F7E820C049D5Af70B16ac266c8f128")}, + {"DAI", "StandardBridge", common.HexToAddress("0x10E6593CDda8c58a1d0f14C5164B376352a55f2F")}, + {"wstETH", "StandardBridge", common.HexToAddress("0x76943C0D61395d8F2edF9060e1533529cAe05dE6")}, + }, + // Kovan + 42: { + {"BitBTC", "StandardBridge", common.HexToAddress("0x0b651A42F32069d62d5ECf4f2a7e5Bd3E9438746")}, + {"USX", "StandardBridge", common.HexToAddress("0x40E862341b2416345F02c41Ac70df08525150dC7")}, + {"DAI", "StandardBridge", common.HexToAddress("0xb415e822C4983ecD6B1c1596e8a5f976cf6CD9e3")}, + {"wstETH", "StandardBridge", common.HexToAddress("0x65321bf24210b81500230dCEce14Faa70a9f50a7")}, + }, +} + +func BridgesByChainID(chainID *big.Int, client bind.ContractBackend, addrs services.AddressManager) (map[string]Bridge, error) { + l1SBAddr, _ := addrs.L1StandardBridge() + allCfgs := []*implConfig{ + {"Standard", "StandardBridge", l1SBAddr}, + {"ETH", "ETHBridge", l1SBAddr}, + } + allCfgs = append(allCfgs, customBridgeCfgs[chainID.Uint64()]...) + + bridges := make(map[string]Bridge) + for _, bridge := range allCfgs { + switch bridge.impl { + case "StandardBridge": + l1SB, err := bindings.NewL1StandardBridge(bridge.addr, client) + if err != nil { + return nil, err + } + standardBridge := &StandardBridge{ + name: bridge.name, + address: bridge.addr, + contract: l1SB, + } + bridges[bridge.name] = standardBridge + case "ETHBridge": + l1SB, err := bindings.NewL1StandardBridge(bridge.addr, client) + if err != nil { + return nil, err + } + ethBridge := &EthBridge{ + name: bridge.name, + address: bridge.addr, + contract: l1SB, + } + bridges[bridge.name] = ethBridge + default: + return nil, errors.New("unsupported bridge") + } + } + return bridges, nil +} + +func StateCommitmentChainScanner(client bind.ContractFilterer, addrs services.AddressManager) (*scc.StateCommitmentChainFilterer, error) { + sccAddr, _ := addrs.StateCommitmentChain() + filter, err := scc.NewStateCommitmentChainFilterer(sccAddr, client) + if err != nil { + return nil, err + } + return filter, nil +} diff --git a/indexer/services/l1/bridge/eth_bridge.go b/indexer/services/l1/bridge/eth_bridge.go index dafa87c084b60..f7d4698c9d312 100644 --- a/indexer/services/l1/bridge/eth_bridge.go +++ b/indexer/services/l1/bridge/eth_bridge.go @@ -5,33 +5,40 @@ import ( "github.com/ethereum-optimism/optimism/indexer/db" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-service/backoff" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) type EthBridge struct { name string - ctx context.Context address common.Address - client bind.ContractFilterer - filterer *bindings.L1StandardBridgeFilterer + contract *bindings.L1StandardBridge } func (e *EthBridge) Address() common.Address { return e.address } -func (e *EthBridge) GetDepositsByBlockRange(start, end uint64) (DepositsMap, error) { +func (e *EthBridge) GetDepositsByBlockRange(ctx context.Context, start, end uint64) (DepositsMap, error) { depositsByBlockhash := make(DepositsMap) + opts := &bind.FilterOpts{ + Context: ctx, + Start: start, + End: &end, + } - iter, err := FilterETHDepositInitiatedWithRetry(e.ctx, e.filterer, &bind.FilterOpts{ - Start: start, - End: &end, + var iter *bindings.L1StandardBridgeETHDepositInitiatedIterator + err := backoff.Do(3, backoff.Exponential(), func() error { + var err error + iter, err = e.contract.FilterETHDepositInitiated(opts, nil, nil) + return err }) if err != nil { - logger.Error("Error fetching filter", "err", err) + return nil, err } + defer iter.Close() for iter.Next() { depositsByBlockhash[iter.Event.Raw.BlockHash] = append( depositsByBlockhash[iter.Event.Raw.BlockHash], db.Deposit{ @@ -43,41 +50,8 @@ func (e *EthBridge) GetDepositsByBlockRange(start, end uint64) (DepositsMap, err LogIndex: iter.Event.Raw.Index, }) } - if err := iter.Error(); err != nil { - return nil, err - } - - return depositsByBlockhash, nil -} - -func (s *EthBridge) GetWithdrawalsByBlockRange(start, end uint64) (WithdrawalsMap, error) { - withdrawalsByBlockHash := make(WithdrawalsMap) - - iter, err := FilterETHWithdrawalFinalizedWithRetry(s.ctx, s.filterer, &bind.FilterOpts{ - Start: start, - End: &end, - }) - - if err != nil { - logger.Error("Error fetching filter", "err", err) - } - - for iter.Next() { - withdrawalsByBlockHash[iter.Event.Raw.BlockHash] = append( - withdrawalsByBlockHash[iter.Event.Raw.BlockHash], db.Withdrawal{ - TxHash: iter.Event.Raw.TxHash, - FromAddress: iter.Event.From, - ToAddress: iter.Event.To, - Amount: iter.Event.Amount, - Data: iter.Event.ExtraData, - LogIndex: iter.Event.Raw.Index, - }) - } - if err := iter.Error(); err != nil { - return nil, err - } - return withdrawalsByBlockHash, nil + return depositsByBlockhash, iter.Error() } func (e *EthBridge) String() string { diff --git a/indexer/services/l1/bridge/filter.go b/indexer/services/l1/bridge/filter.go index d7d8b02b65146..a68e38b73ee00 100644 --- a/indexer/services/l1/bridge/filter.go +++ b/indexer/services/l1/bridge/filter.go @@ -4,7 +4,7 @@ import ( "context" "time" - "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/indexer/bindings/legacy/scc" "github.com/ethereum/go-ethereum/accounts/abi/bind" ) @@ -12,61 +12,13 @@ import ( // calls. var clientRetryInterval = 5 * time.Second -// FilterETHDepositInitiatedWithRetry retries the given func until it succeeds, +// FilterStateBatchAppendedWithRetry retries the given func until it succeeds, // waiting for clientRetryInterval duration after every call. -func FilterETHDepositInitiatedWithRetry(ctx context.Context, filterer *bindings.L1StandardBridgeFilterer, opts *bind.FilterOpts) (*bindings.L1StandardBridgeETHDepositInitiatedIterator, error) { +func FilterStateBatchAppendedWithRetry(ctx context.Context, filterer *scc.StateCommitmentChainFilterer, opts *bind.FilterOpts) (*scc.StateCommitmentChainStateBatchAppendedIterator, error) { for { ctxt, cancel := context.WithTimeout(ctx, DefaultConnectionTimeout) opts.Context = ctxt - res, err := filterer.FilterETHDepositInitiated(opts, nil, nil) - cancel() - if err == nil { - return res, nil - } - logger.Error("Error fetching filter", "err", err) - time.Sleep(clientRetryInterval) - } -} - -// FilterERC20DepositInitiatedWithRetry retries the given func until it succeeds, -// waiting for clientRetryInterval duration after every call. -func FilterERC20DepositInitiatedWithRetry(ctx context.Context, filterer *bindings.L1StandardBridgeFilterer, opts *bind.FilterOpts) (*bindings.L1StandardBridgeERC20DepositInitiatedIterator, error) { - for { - ctxt, cancel := context.WithTimeout(ctx, DefaultConnectionTimeout) - opts.Context = ctxt - res, err := filterer.FilterERC20DepositInitiated(opts, nil, nil, nil) - cancel() - if err == nil { - return res, nil - } - logger.Error("Error fetching filter", "err", err) - time.Sleep(clientRetryInterval) - } -} - -// FilterETHWithdrawalFinalizedWithRetry retries the given func until it succeeds, -// waiting for clientRetryInterval duration after every call. -func FilterETHWithdrawalFinalizedWithRetry(ctx context.Context, filterer *bindings.L1StandardBridgeFilterer, opts *bind.FilterOpts) (*bindings.L1StandardBridgeETHWithdrawalFinalizedIterator, error) { - for { - ctxt, cancel := context.WithTimeout(ctx, DefaultConnectionTimeout) - opts.Context = ctxt - res, err := filterer.FilterETHWithdrawalFinalized(opts, nil, nil) - cancel() - if err == nil { - return res, nil - } - logger.Error("Error fetching filter", "err", err) - time.Sleep(clientRetryInterval) - } -} - -// FilterERC20WithdrawalFinalizedWithRetry retries the given func until it succeeds, -// waiting for clientRetryInterval duration after every call. -func FilterERC20WithdrawalFinalizedWithRetry(ctx context.Context, filterer *bindings.L1StandardBridgeFilterer, opts *bind.FilterOpts) (*bindings.L1StandardBridgeERC20WithdrawalFinalizedIterator, error) { - for { - ctxt, cancel := context.WithTimeout(ctx, DefaultConnectionTimeout) - opts.Context = ctxt - res, err := filterer.FilterERC20WithdrawalFinalized(opts, nil, nil, nil) + res, err := filterer.FilterStateBatchAppended(opts, nil) cancel() if err == nil { return res, nil diff --git a/indexer/services/l1/bridge/portal.go b/indexer/services/l1/bridge/portal.go new file mode 100644 index 0000000000000..6a2c3efb08aa3 --- /dev/null +++ b/indexer/services/l1/bridge/portal.go @@ -0,0 +1,63 @@ +package bridge + +import ( + "context" + + "github.com/ethereum-optimism/optimism/indexer/db" + "github.com/ethereum-optimism/optimism/indexer/services" + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-service/backoff" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +type Portal struct { + address common.Address + contract *bindings.OptimismPortal +} + +func NewPortal(addrs services.AddressManager) *Portal { + address, contract := addrs.OptimismPortal() + + return &Portal{ + address: address, + contract: contract, + } +} + +func (p *Portal) Address() common.Address { + return p.address +} + +func (p *Portal) GetFinalizedWithdrawalsByBlockRange(ctx context.Context, start, end uint64) (FinalizedWithdrawalsMap, error) { + wdsByBlockHash := make(FinalizedWithdrawalsMap) + opts := &bind.FilterOpts{ + Context: ctx, + Start: start, + End: &end, + } + + var iter *bindings.OptimismPortalWithdrawalFinalizedIterator + err := backoff.Do(3, backoff.Exponential(), func() error { + var err error + iter, err = p.contract.FilterWithdrawalFinalized(opts, nil) + return err + }) + if err != nil { + return nil, err + } + + defer iter.Close() + for iter.Next() { + wdsByBlockHash[iter.Event.Raw.BlockHash] = append( + wdsByBlockHash[iter.Event.Raw.BlockHash], db.FinalizedWithdrawal{ + TxHash: iter.Event.Raw.TxHash, + WithdrawalHash: iter.Event.WithdrawalHash, + Success: iter.Event.Success, + LogIndex: iter.Event.Raw.Index, + }, + ) + } + + return wdsByBlockHash, iter.Error() +} diff --git a/indexer/services/l1/bridge/standard_bridge.go b/indexer/services/l1/bridge/standard_bridge.go index 031704bbc8071..b45412801ff2b 100644 --- a/indexer/services/l1/bridge/standard_bridge.go +++ b/indexer/services/l1/bridge/standard_bridge.go @@ -5,33 +5,40 @@ import ( "github.com/ethereum-optimism/optimism/indexer/db" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-service/backoff" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) type StandardBridge struct { name string - ctx context.Context address common.Address - client bind.ContractFilterer - filterer *bindings.L1StandardBridgeFilterer + contract *bindings.L1StandardBridge } func (s *StandardBridge) Address() common.Address { return s.address } -func (s *StandardBridge) GetDepositsByBlockRange(start, end uint64) (DepositsMap, error) { +func (s *StandardBridge) GetDepositsByBlockRange(ctx context.Context, start, end uint64) (DepositsMap, error) { depositsByBlockhash := make(DepositsMap) + opts := &bind.FilterOpts{ + Context: ctx, + Start: start, + End: &end, + } - iter, err := FilterERC20DepositInitiatedWithRetry(s.ctx, s.filterer, &bind.FilterOpts{ - Start: start, - End: &end, + var iter *bindings.L1StandardBridgeERC20DepositInitiatedIterator + err := backoff.Do(3, backoff.Exponential(), func() error { + var err error + iter, err = s.contract.FilterERC20DepositInitiated(opts, nil, nil, nil) + return err }) if err != nil { - logger.Error("Error fetching filter", "err", err) + return nil, err } + defer iter.Close() for iter.Next() { depositsByBlockhash[iter.Event.Raw.BlockHash] = append( depositsByBlockhash[iter.Event.Raw.BlockHash], db.Deposit{ @@ -45,43 +52,8 @@ func (s *StandardBridge) GetDepositsByBlockRange(start, end uint64) (DepositsMap LogIndex: iter.Event.Raw.Index, }) } - if err := iter.Error(); err != nil { - return nil, err - } - - return depositsByBlockhash, nil -} - -func (s *StandardBridge) GetWithdrawalsByBlockRange(start, end uint64) (WithdrawalsMap, error) { - withdrawalsByBlockHash := make(WithdrawalsMap) - - iter, err := FilterERC20WithdrawalFinalizedWithRetry(s.ctx, s.filterer, &bind.FilterOpts{ - Start: start, - End: &end, - }) - - if err != nil { - logger.Error("Error fetching filter", "err", err) - } - - for iter.Next() { - withdrawalsByBlockHash[iter.Event.Raw.BlockHash] = append( - withdrawalsByBlockHash[iter.Event.Raw.BlockHash], db.Withdrawal{ - TxHash: iter.Event.Raw.TxHash, - L1Token: iter.Event.L1Token, - L2Token: iter.Event.L2Token, - FromAddress: iter.Event.From, - ToAddress: iter.Event.To, - Amount: iter.Event.Amount, - Data: iter.Event.ExtraData, - LogIndex: iter.Event.Raw.Index, - }) - } - if err := iter.Error(); err != nil { - return nil, err - } - return withdrawalsByBlockHash, nil + return depositsByBlockhash, iter.Error() } func (s *StandardBridge) String() string { diff --git a/indexer/services/l1/confirmed_headers.go b/indexer/services/l1/confirmed_headers.go index aa472448fba51..3c1a9fdc0ea20 100644 --- a/indexer/services/l1/confirmed_headers.go +++ b/indexer/services/l1/confirmed_headers.go @@ -17,9 +17,8 @@ import ( ) const ( - DefaultConnectionTimeout = 30 * time.Second - DefaultConfDepth uint64 = 20 - DefaultMaxBatchSize = 100 + DefaultConnectionTimeout = 30 * time.Second + DefaultMaxBatchSize = 100 ) type NewHeader struct { diff --git a/indexer/services/l1/query.go b/indexer/services/l1/query.go index 4910ea596a0c4..8f2bb8cae311f 100644 --- a/indexer/services/l1/query.go +++ b/indexer/services/l1/query.go @@ -1,38 +1,37 @@ package l1 import ( - "github.com/ethereum/go-ethereum/ethclient" + "context" + "github.com/ethereum-optimism/optimism/indexer/bindings/legacy/scc" "github.com/ethereum-optimism/optimism/indexer/db" - "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/indexer/services/l1/bridge" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) -func QueryERC20(address common.Address, client *ethclient.Client) (*db.Token, error) { - contract, err := bindings.NewERC20(address, client) - if err != nil { - return nil, err - } - - name, err := contract.Name(&bind.CallOpts{}) - if err != nil { - return nil, err - } +func QueryStateBatches(filterer *scc.StateCommitmentChainFilterer, startHeight, endHeight uint64, ctx context.Context) (map[common.Hash][]db.StateBatch, error) { + batches := make(map[common.Hash][]db.StateBatch) - symbol, err := contract.Symbol(&bind.CallOpts{}) + iter, err := bridge.FilterStateBatchAppendedWithRetry(ctx, filterer, &bind.FilterOpts{ + Start: startHeight, + End: &endHeight, + }) if err != nil { return nil, err } - decimals, err := contract.Decimals(&bind.CallOpts{}) - if err != nil { - return nil, err + defer iter.Close() + for iter.Next() { + batches[iter.Event.Raw.BlockHash] = append( + batches[iter.Event.Raw.BlockHash], db.StateBatch{ + Index: iter.Event.BatchIndex, + Root: iter.Event.BatchRoot, + Size: iter.Event.BatchSize, + PrevTotal: iter.Event.PrevTotalElements, + ExtraData: iter.Event.ExtraData, + BlockHash: iter.Event.Raw.BlockHash, + }) } - - return &db.Token{ - Name: name, - Symbol: symbol, - Decimals: decimals, - }, nil + return batches, iter.Error() } diff --git a/indexer/services/l1/service.go b/indexer/services/l1/service.go index 7d026528ba650..b660a80e73d71 100644 --- a/indexer/services/l1/service.go +++ b/indexer/services/l1/service.go @@ -11,7 +11,10 @@ import ( "sync/atomic" "time" + "github.com/ethereum-optimism/optimism/indexer/bindings/legacy/scc" "github.com/ethereum-optimism/optimism/indexer/metrics" + "github.com/ethereum-optimism/optimism/indexer/services" + "github.com/ethereum-optimism/optimism/indexer/services/query" "github.com/prometheus/client_golang/prometheus" "github.com/ethereum-optimism/optimism/indexer/server" @@ -36,28 +39,8 @@ var errNoChainID = errors.New("no chain id provided") var errNoNewBlocks = errors.New("no new blocks") -// clientRetryInterval is the interval to wait between retrying client API -// calls. -var clientRetryInterval = 5 * time.Second - var ZeroAddress common.Address -// HeaderByNumberWithRetry retries the given func until it succeeds, waiting -// for clientRetryInterval duration after every call. -func HeaderByNumberWithRetry(ctx context.Context, - client *ethclient.Client) (*types.Header, error) { - for { - res, err := client.HeaderByNumber(ctx, nil) - switch err { - case nil: - return res, err - default: - log.Error("Error fetching header", "err", err) - } - time.Sleep(clientRetryInterval) - } -} - // Driver is an interface for indexing deposits from l1. type Driver interface { // Name is an identifier used to prefix logs for a particular service. @@ -70,11 +53,12 @@ type ServiceConfig struct { L1Client *ethclient.Client RawL1Client *rpc.Client ChainID *big.Int + AddressManager services.AddressManager ConfDepth uint64 MaxHeaderBatchSize uint64 StartBlockNumber uint64 - StartBlockHash string DB *db.Database + Bedrock bool } type Service struct { @@ -83,11 +67,14 @@ type Service struct { cancel func() bridges map[string]bridge.Bridge + portal *bridge.Portal + batchScanner *scc.StateCommitmentChainFilterer latestHeader uint64 headerSelector *ConfirmedHeaderSelector metrics *metrics.Metrics tokenCache map[common.Address]*db.Token + isBedrock bool wg sync.WaitGroup } @@ -113,11 +100,24 @@ func NewService(cfg ServiceConfig) (*Service, error) { return nil, fmt.Errorf("chain ID configured with %d but got %d", cfg.ChainID, chainID) } - bridges, err := bridge.BridgesByChainID(cfg.ChainID, cfg.L1Client, ctx) + bridges, err := bridge.BridgesByChainID(cfg.ChainID, cfg.L1Client, cfg.AddressManager) if err != nil { cancel() return nil, err } + + var portal *bridge.Portal + var batchScanner *scc.StateCommitmentChainFilterer + if cfg.Bedrock { + portal = bridge.NewPortal(cfg.AddressManager) + } else { + batchScanner, err = bridge.StateCommitmentChainScanner(cfg.L1Client, cfg.AddressManager) + if err != nil { + cancel() + return nil, err + } + } + logger.Info("Scanning bridges for deposits", "bridges", bridges) confirmedHeaderSelector, err := NewConfirmedHeaderSelector(HeaderSelectorConfig{ @@ -130,22 +130,29 @@ func NewService(cfg ServiceConfig) (*Service, error) { return nil, err } - return &Service{ + service := &Service{ cfg: cfg, ctx: ctx, cancel: cancel, + portal: portal, bridges: bridges, + batchScanner: batchScanner, headerSelector: confirmedHeaderSelector, metrics: cfg.Metrics, tokenCache: map[common.Address]*db.Token{ ZeroAddress: db.ETHL1Token, }, - }, nil + isBedrock: cfg.Bedrock, + } + service.wg.Add(1) + return service, nil } -func (s *Service) Loop(ctx context.Context) { +func (s *Service) loop() { + defer s.wg.Done() + for { - err := s.catchUp(ctx) + err := s.catchUp() if err == nil { break } @@ -159,10 +166,18 @@ func (s *Service) Loop(ctx context.Context) { } newHeads := make(chan *types.Header, 1000) - go s.subscribeNewHeads(ctx, newHeads) + tick := time.NewTicker(5 * time.Second) + defer tick.Stop() for { select { + case <-tick.C: + header, err := query.HeaderByNumberWithRetry(s.ctx, s.cfg.L1Client) + if err != nil { + logger.Error("error fetching header by number", "err", err) + continue + } + newHeads <- header case header := <-newHeads: if header == nil { break @@ -180,6 +195,7 @@ func (s *Service) Loop(ctx context.Context) { } } case <-s.ctx.Done(): + logger.Info("service stopped") return } } @@ -188,7 +204,6 @@ func (s *Service) Loop(ctx context.Context) { func (s *Service) Update(newHeader *types.Header) error { var lowest = db.BlockLocator{ Number: s.cfg.StartBlockNumber, - Hash: common.HexToHash(s.cfg.StartBlockHash), } highestConfirmed, err := s.cfg.DB.GetHighestL1Block() if err != nil { @@ -213,7 +228,7 @@ func (s *Service) Update(newHeader *types.Header) error { return nil } - if lowest.Hash != headers[0].ParentHash { + if lowest.Number > 0 && lowest.Hash != headers[0].ParentHash { logger.Error("Parent hash does not connect to ", "block", headers[0].Number.Uint64(), "hash", headers[0].Hash, "lowest_block", lowest.Number, "hash", lowest.Hash) @@ -223,7 +238,6 @@ func (s *Service) Update(newHeader *types.Header) error { startHeight := headers[0].Number.Uint64() endHeight := headers[len(headers)-1].Number.Uint64() depositsByBlockHash := make(map[common.Hash][]db.Deposit) - withdrawalsByBlockHash := make(map[common.Hash][]db.Withdrawal) start := prometheus.NewTimer(s.metrics.UpdateDuration.WithLabelValues("l1")) defer func() { @@ -232,27 +246,27 @@ func (s *Service) Update(newHeader *types.Header) error { }() bridgeDepositsCh := make(chan bridge.DepositsMap, len(s.bridges)) - bridgeWdsCh := make(chan bridge.WithdrawalsMap, len(s.bridges)) - errCh := make(chan error, len(s.bridges)) + finalizedWithdrawalsCh := make(chan bridge.FinalizedWithdrawalsMap, 1) + errCh := make(chan error, len(s.bridges)+1) for _, bridgeImpl := range s.bridges { go func(b bridge.Bridge) { - deposits, err := b.GetDepositsByBlockRange(startHeight, endHeight) + deposits, err := b.GetDepositsByBlockRange(s.ctx, startHeight, endHeight) if err != nil { errCh <- err return } bridgeDepositsCh <- deposits }(bridgeImpl) - go func(b bridge.Bridge) { - withdrawals, err := b.GetWithdrawalsByBlockRange(startHeight, endHeight) - if err != nil { - errCh <- err - return - } - bridgeWdsCh <- withdrawals - }(bridgeImpl) } + go func() { + finalizedWithdrawals, err := s.portal.GetFinalizedWithdrawalsByBlockRange(s.ctx, startHeight, endHeight) + if err != nil { + errCh <- err + return + } + finalizedWithdrawalsCh <- finalizedWithdrawals + }() var receives int for { @@ -260,50 +274,54 @@ func (s *Service) Update(newHeader *types.Header) error { case bridgeDeposits := <-bridgeDepositsCh: for blockHash, deposits := range bridgeDeposits { for _, deposit := range deposits { - if err := s.cacheToken(deposit.L1Token); err != nil { + if err := s.cacheToken(deposit); err != nil { logger.Warn("error caching token", "err", err) } } depositsByBlockHash[blockHash] = append(depositsByBlockHash[blockHash], deposits...) } - case bridgeWithdrawals := <-bridgeWdsCh: - for blockHash, withdrawals := range bridgeWithdrawals { - for _, withdrawal := range withdrawals { - if err := s.cacheToken(withdrawal.L1Token); err != nil { - logger.Warn("error caching token", "err", err) - } - } - - withdrawalsByBlockHash[blockHash] = append(withdrawalsByBlockHash[blockHash], withdrawals...) - } case err := <-errCh: return err } receives++ - if receives == 2*len(s.bridges) { + if receives == len(s.bridges) { break } } + finalizedWithdrawalsByBlockHash := <-finalizedWithdrawalsCh + + var stateBatches map[common.Hash][]db.StateBatch + if !s.isBedrock { + stateBatches, err = QueryStateBatches(s.batchScanner, startHeight, endHeight, s.ctx) + if err != nil { + logger.Error("Error querying state batches", "err", err) + return err + } + } + for i, header := range headers { blockHash := header.Hash number := header.Number.Uint64() deposits := depositsByBlockHash[blockHash] - withdrawals := withdrawalsByBlockHash[blockHash] + batches := stateBatches[blockHash] + finalizedWds := finalizedWithdrawalsByBlockHash[blockHash] - if len(deposits) == 0 && len(withdrawals) == 0 && i != len(headers)-1 { + // Always record block data in the last block + // in the list of headers + if len(deposits) == 0 && len(batches) == 0 && len(finalizedWds) == 0 && i != len(headers)-1 { continue } block := &db.IndexedL1Block{ - Hash: blockHash, - ParentHash: header.ParentHash, - Number: number, - Timestamp: header.Time, - Deposits: deposits, - Withdrawals: withdrawals, + Hash: blockHash, + ParentHash: header.ParentHash, + Number: number, + Timestamp: header.Time, + Deposits: deposits, + FinalizedWithdrawals: finalizedWds, } err := s.cfg.DB.AddIndexedL1Block(block) @@ -311,24 +329,35 @@ func (s *Service) Update(newHeader *types.Header) error { logger.Error( "Unable to import ", "block", number, - "hash", blockHash, - "err", err, + "hash", blockHash, "err", err, + "block", block, + ) + return err + } + + err = s.cfg.DB.AddStateBatch(batches) + if err != nil { + logger.Error( + "Unable to import state append batch", + "block", number, + "hash", blockHash, "err", err, "block", block, ) return err } + s.metrics.RecordStateBatches(len(batches)) logger.Debug("Imported ", "block", number, "hash", blockHash, "deposits", len(block.Deposits)) for _, deposit := range block.Deposits { - token := s.tokenCache[deposit.L2Token] + token := s.tokenCache[deposit.L1Token] logger.Info( - "indexed deposit ", + "indexed deposit", "tx_hash", deposit.TxHash, "symbol", token.Symbol, "amount", deposit.Amount, ) - s.metrics.RecordDeposit(deposit.L2Token) + s.metrics.RecordDeposit(deposit.L1Token) } } @@ -383,8 +412,8 @@ func (s *Service) GetDeposits(w http.ResponseWriter, r *http.Request) { } page := db.PaginationParam{ - Limit: uint64(limit), - Offset: uint64(offset), + Limit: limit, + Offset: offset, } deposits, err := s.cfg.DB.GetDepositsByAddress(common.HexToAddress(vars["address"]), page) @@ -396,25 +425,8 @@ func (s *Service) GetDeposits(w http.ResponseWriter, r *http.Request) { server.RespondWithJSON(w, http.StatusOK, deposits) } -func (s *Service) subscribeNewHeads(ctx context.Context, heads chan *types.Header) { - tick := time.NewTicker(5 * time.Second) - - for { - select { - case <-tick.C: - header, err := HeaderByNumberWithRetry(ctx, s.cfg.L1Client) - if err != nil { - logger.Error("error fetching header by number", "err", err) - } - heads <- header - case <-ctx.Done(): - return - } - } -} - -func (s *Service) catchUp(ctx context.Context) error { - realHead, err := HeaderByNumberWithRetry(ctx, s.cfg.L1Client) +func (s *Service) catchUp() error { + realHead, err := query.HeaderByNumberWithRetry(s.ctx, s.cfg.L1Client) if err != nil { return err } @@ -438,8 +450,8 @@ func (s *Service) catchUp(ctx context.Context) error { for realHeadNum-s.cfg.ConfDepth > currHeadNum+s.cfg.MaxHeaderBatchSize { select { - case <-ctx.Done(): - return context.Canceled + case <-s.ctx.Done(): + return s.ctx.Err() default: if err := s.Update(realHead); err != nil && err != errNoNewBlocks { return err @@ -457,33 +469,33 @@ func (s *Service) catchUp(ctx context.Context) error { return nil } -func (s *Service) cacheToken(address common.Address) error { - if s.tokenCache[address] != nil { +func (s *Service) cacheToken(deposit db.Deposit) error { + if s.tokenCache[deposit.L1Token] != nil { return nil } - token, err := s.cfg.DB.GetL1TokenByAddress(address.String()) + token, err := s.cfg.DB.GetL1TokenByAddress(deposit.L1Token.String()) if err != nil { return err } if token != nil { s.metrics.IncL1CachedTokensCount() - s.tokenCache[address] = token + s.tokenCache[deposit.L1Token] = token return nil } - token, err = QueryERC20(address, s.cfg.L1Client) + token, err = query.NewERC20(deposit.L1Token, s.cfg.L1Client) if err != nil { logger.Error("Error querying ERC20 token details", - "l1_token", address.String(), "err", err) + "l1_token", deposit.L1Token.String(), "err", err) token = &db.Token{ - Address: address.String(), + Address: deposit.L1Token.String(), } } - if err := s.cfg.DB.AddL1Token(address.String(), token); err != nil { + if err := s.cfg.DB.AddL1Token(deposit.L1Token.String(), token); err != nil { return err } - s.tokenCache[address] = token + s.tokenCache[deposit.L1Token] = token s.metrics.IncL1CachedTokensCount() return nil } @@ -492,16 +504,11 @@ func (s *Service) Start() error { if s.cfg.ChainID == nil { return errNoChainID } - s.wg.Add(1) - go s.Loop(s.ctx) + go s.loop() return nil } func (s *Service) Stop() { s.cancel() s.wg.Wait() - err := s.cfg.DB.Close() - if err != nil { - logger.Error("Error closing db", "err", err) - } } diff --git a/indexer/services/l2/bridge/bridge.go b/indexer/services/l2/bridge/bridge.go index 49e4c243d8101..a672fc2ff8553 100644 --- a/indexer/services/l2/bridge/bridge.go +++ b/indexer/services/l2/bridge/bridge.go @@ -7,75 +7,76 @@ import ( "github.com/ethereum-optimism/optimism/indexer/db" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) -type DepositsMap map[common.Hash][]db.Deposit // Finalizations type WithdrawalsMap map[common.Hash][]db.Withdrawal type Bridge interface { Address() common.Address - GetDepositsByBlockRange(uint64, uint64) (DepositsMap, error) - GetWithdrawalsByBlockRange(uint64, uint64) (WithdrawalsMap, error) + GetWithdrawalsByBlockRange(context.Context, uint64, uint64) (WithdrawalsMap, error) String() string } type implConfig struct { name string impl string - addr string + addr common.Address } -var defaultBridgeCfgs = map[uint64][]*implConfig{ - // Devnet - 901: { - {"Standard", "StandardBridge", L2StandardBridgeAddr}, - }, - // Goerli Alpha Testnet - 28528: { - {"Standard", "StandardBridge", L2StandardBridgeAddr}, - }, +var defaultBridgeCfgs = []*implConfig{ + {"Standard", "StandardBridge", predeploys.L2StandardBridgeAddr}, } var customBridgeCfgs = map[uint64][]*implConfig{ // Mainnet 10: { - {"BitBTC", StandardBridgeImpl, "0x158F513096923fF2d3aab2BcF4478536de6725e2"}, + {"BitBTC", StandardBridgeImpl, common.HexToAddress("0x158F513096923fF2d3aab2BcF4478536de6725e2")}, //{"DAI", "DAIBridge", "0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65"}, + {"wstETH", StandardBridgeImpl, common.HexToAddress("0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957")}, }, // Kovan 69: { - {"BitBTC", StandardBridgeImpl, "0x0CFb46528a7002a7D8877a5F7a69b9AaF1A9058e"}, - {"USX", StandardBridgeImpl, "0xB4d37826b14Cd3CB7257A2A5094507d701fe715f"}, + {"BitBTC", StandardBridgeImpl, common.HexToAddress("0x0CFb46528a7002a7D8877a5F7a69b9AaF1A9058e")}, + {"USX", StandardBridgeImpl, common.HexToAddress("0xB4d37826b14Cd3CB7257A2A5094507d701fe715f")}, + {"wstETH", StandardBridgeImpl, common.HexToAddress("0x2E34e7d705AfaC3C4665b6feF31Aa394A1c81c92")}, //{"DAI", " DAIBridge", "0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65"}, }, } -func BridgesByChainID(chainID *big.Int, client bind.ContractFilterer, ctx context.Context) (map[string]Bridge, error) { +func BridgesByChainID(chainID *big.Int, client *ethclient.Client, isBedrock bool) (map[string]Bridge, error) { allCfgs := make([]*implConfig, 0) - allCfgs = append(allCfgs, defaultBridgeCfgs[chainID.Uint64()]...) + allCfgs = append(allCfgs, defaultBridgeCfgs...) allCfgs = append(allCfgs, customBridgeCfgs[chainID.Uint64()]...) + var l2L1MP *bindings.L2ToL1MessagePasser + var err error + if isBedrock { + l2L1MP, err = bindings.NewL2ToL1MessagePasser(predeploys.L2ToL1MessagePasserAddr, client) + if err != nil { + return nil, err + } + } + bridges := make(map[string]Bridge) for _, bridge := range allCfgs { switch bridge.impl { case "StandardBridge": - l2StandardBridgeAddress := common.HexToAddress(bridge.addr) - l2StandardBridgeFilter, err := bindings.NewL2StandardBridgeFilterer(l2StandardBridgeAddress, client) + l2SB, err := bindings.NewL2StandardBridge(bridge.addr, client) if err != nil { return nil, err } - - standardBridge := &StandardBridge{ - name: bridge.name, - ctx: ctx, - address: l2StandardBridgeAddress, - client: client, - filterer: l2StandardBridgeFilter, + bridges[bridge.name] = &StandardBridge{ + name: bridge.name, + address: bridge.addr, + client: client, + l2SB: l2SB, + l2L1MP: l2L1MP, + isBedrock: isBedrock, } - bridges[bridge.name] = standardBridge default: return nil, errors.New("unsupported bridge") } diff --git a/indexer/services/l2/bridge/filter.go b/indexer/services/l2/bridge/filter.go deleted file mode 100644 index 4ab39493adb14..0000000000000 --- a/indexer/services/l2/bridge/filter.go +++ /dev/null @@ -1,45 +0,0 @@ -package bridge - -import ( - "context" - "time" - - "github.com/ethereum-optimism/optimism/op-bindings/bindings" - "github.com/ethereum/go-ethereum/accounts/abi/bind" -) - -// clientRetryInterval is the interval to wait between retrying client API -// calls. -var clientRetryInterval = 5 * time.Second - -// FilterWithdrawalInitiatedWithRetry retries the given func until it succeeds, -// waiting for clientRetryInterval duration after every call. -func FilterWithdrawalInitiatedWithRetry(ctx context.Context, filterer *bindings.L2StandardBridgeFilterer, opts *bind.FilterOpts) (*bindings.L2StandardBridgeWithdrawalInitiatedIterator, error) { - for { - ctxt, cancel := context.WithTimeout(ctx, DefaultConnectionTimeout) - opts.Context = ctxt - res, err := filterer.FilterWithdrawalInitiated(opts, nil, nil, nil) - cancel() - if err == nil { - return res, nil - } - logger.Error("Error fetching filter", "err", err) - time.Sleep(clientRetryInterval) - } -} - -// FilterDepositFinalizedWithRetry retries the given func until it succeeds, -// waiting for clientRetryInterval duration after every call. -func FilterDepositFinalizedWithRetry(ctx context.Context, filterer *bindings.L2StandardBridgeFilterer, opts *bind.FilterOpts) (*bindings.L2StandardBridgeDepositFinalizedIterator, error) { - for { - ctxt, cancel := context.WithTimeout(ctx, DefaultConnectionTimeout) - opts.Context = ctxt - res, err := filterer.FilterDepositFinalized(opts, nil, nil, nil) - cancel() - if err == nil { - return res, nil - } - logger.Error("Error fetching filter", "err", err) - time.Sleep(clientRetryInterval) - } -} diff --git a/indexer/services/l2/bridge/standard_bridge.go b/indexer/services/l2/bridge/standard_bridge.go index fdbed6863b61f..51f3ae83a0b6d 100644 --- a/indexer/services/l2/bridge/standard_bridge.go +++ b/indexer/services/l2/bridge/standard_bridge.go @@ -5,83 +5,112 @@ import ( "github.com/ethereum-optimism/optimism/indexer/db" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-node/withdrawals" + "github.com/ethereum-optimism/optimism/op-service/backoff" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) type StandardBridge struct { - name string - ctx context.Context - address common.Address - client bind.ContractFilterer - filterer *bindings.L2StandardBridgeFilterer + name string + address common.Address + client *ethclient.Client + l2SB *bindings.L2StandardBridge + l2L1MP *bindings.L2ToL1MessagePasser + isBedrock bool } func (s *StandardBridge) Address() common.Address { return s.address } -func (s *StandardBridge) GetDepositsByBlockRange(start, end uint64) (DepositsMap, error) { - depositsByBlockhash := make(DepositsMap) +func (s *StandardBridge) GetWithdrawalsByBlockRange(ctx context.Context, start, end uint64) (WithdrawalsMap, error) { + withdrawalsByBlockhash := make(map[common.Hash][]db.Withdrawal) + opts := &bind.FilterOpts{ + Context: ctx, + Start: start, + End: &end, + } - iter, err := FilterDepositFinalizedWithRetry(s.ctx, s.filterer, &bind.FilterOpts{ - Start: start, - End: &end, + var iter *bindings.L2StandardBridgeWithdrawalInitiatedIterator + err := backoff.Do(3, backoff.Exponential(), func() error { + var err error + iter, err = s.l2SB.FilterWithdrawalInitiated(opts, nil, nil, nil) + return err }) if err != nil { - logger.Error("Error fetching filter", "err", err) + return nil, err } + receipts := make(map[common.Hash]*types.Receipt) + defer iter.Close() for iter.Next() { - depositsByBlockhash[iter.Event.Raw.BlockHash] = append( - depositsByBlockhash[iter.Event.Raw.BlockHash], db.Deposit{ - TxHash: iter.Event.Raw.TxHash, - L1Token: iter.Event.L1Token, - L2Token: iter.Event.L2Token, - FromAddress: iter.Event.From, - ToAddress: iter.Event.To, - Amount: iter.Event.Amount, - Data: iter.Event.ExtraData, - LogIndex: iter.Event.Raw.Index, - }) - } - if err := iter.Error(); err != nil { - return nil, err - } + ev := iter.Event + if s.isBedrock { + receipt := receipts[ev.Raw.TxHash] + if receipt == nil { + receipt, err = s.client.TransactionReceipt(ctx, ev.Raw.TxHash) + if err != nil { + return nil, err + } + receipts[ev.Raw.TxHash] = receipt + } - return depositsByBlockhash, nil -} + var withdrawalInitiated *bindings.L2ToL1MessagePasserMessagePassed + for _, eLog := range receipt.Logs { + if len(eLog.Topics) == 0 || eLog.Topics[0] != withdrawals.MessagePassedTopic { + continue + } -func (s *StandardBridge) GetWithdrawalsByBlockRange(start, end uint64) (WithdrawalsMap, error) { - withdrawalsByBlockhash := make(map[common.Hash][]db.Withdrawal) + if withdrawalInitiated != nil { + logger.Warn("detected multiple withdrawal initiated events! ignoring", "tx_hash", ev.Raw.TxHash) + continue + } - iter, err := FilterWithdrawalInitiatedWithRetry(s.ctx, s.filterer, &bind.FilterOpts{ - Start: start, - End: &end, - }) - if err != nil { - logger.Error("Error fetching filter", "err", err) - } + withdrawalInitiated, err = s.l2L1MP.ParseMessagePassed(*eLog) + if err != nil { + return nil, err + } + } - for iter.Next() { - withdrawalsByBlockhash[iter.Event.Raw.BlockHash] = append( - withdrawalsByBlockhash[iter.Event.Raw.BlockHash], db.Withdrawal{ - TxHash: iter.Event.Raw.TxHash, - L1Token: iter.Event.L1Token, - L2Token: iter.Event.L2Token, - FromAddress: iter.Event.From, - ToAddress: iter.Event.To, - Amount: iter.Event.Amount, - Data: iter.Event.ExtraData, - LogIndex: iter.Event.Raw.Index, - }) - } - if err := iter.Error(); err != nil { - return nil, err + hash, err := withdrawals.WithdrawalHash(withdrawalInitiated) + if err != nil { + return nil, err + } + + withdrawalsByBlockhash[ev.Raw.BlockHash] = append( + withdrawalsByBlockhash[ev.Raw.BlockHash], db.Withdrawal{ + TxHash: ev.Raw.TxHash, + L1Token: ev.L1Token, + L2Token: ev.L2Token, + FromAddress: ev.From, + ToAddress: ev.To, + Amount: ev.Amount, + Data: ev.ExtraData, + LogIndex: ev.Raw.Index, + BedrockHash: &hash, + }, + ) + } else { + withdrawalsByBlockhash[ev.Raw.BlockHash] = append( + withdrawalsByBlockhash[ev.Raw.BlockHash], db.Withdrawal{ + TxHash: ev.Raw.TxHash, + L1Token: ev.L1Token, + L2Token: ev.L2Token, + FromAddress: ev.From, + ToAddress: ev.To, + Amount: ev.Amount, + Data: ev.ExtraData, + LogIndex: ev.Raw.Index, + }, + ) + } } - return withdrawalsByBlockhash, nil + return withdrawalsByBlockhash, iter.Error() } func (s *StandardBridge) String() string { diff --git a/indexer/services/l2/confirmed_headers.go b/indexer/services/l2/confirmed_headers.go index 4e6811341701f..72b9e75c3eafd 100644 --- a/indexer/services/l2/confirmed_headers.go +++ b/indexer/services/l2/confirmed_headers.go @@ -147,8 +147,7 @@ func (f *ConfirmedHeaderSelector) NewHead( return headers, nil } -func NewConfirmedHeaderSelector(cfg HeaderSelectorConfig) (*ConfirmedHeaderSelector, - error) { +func NewConfirmedHeaderSelector(cfg HeaderSelectorConfig) (*ConfirmedHeaderSelector, error) { if cfg.ConfDepth == 0 { return nil, errors.New("ConfDepth must be greater than zero") } diff --git a/indexer/services/l2/service.go b/indexer/services/l2/service.go index 410b5179ca7ed..d508b8f882977 100644 --- a/indexer/services/l2/service.go +++ b/indexer/services/l2/service.go @@ -12,6 +12,8 @@ import ( "github.com/ethereum-optimism/optimism/indexer/metrics" "github.com/ethereum-optimism/optimism/indexer/server" + "github.com/ethereum-optimism/optimism/indexer/services/query" + "github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/prometheus/client_golang/prometheus" "github.com/ethereum-optimism/optimism/indexer/db" @@ -38,37 +40,18 @@ var errWrongChainID = errors.New("wrong chain id provided") var errNoNewBlocks = errors.New("no new blocks") -// clientRetryInterval is the interval to wait between retrying client API -// calls. -var clientRetryInterval = 5 * time.Second - -// HeaderByNumberWithRetry retries the given func until it succeeds, waiting -// for clientRetryInterval duration after every call. -func HeaderByNumberWithRetry(ctx context.Context, - client *ethclient.Client) (*types.Header, error) { - for { - res, err := client.HeaderByNumber(ctx, nil) - switch err { - case nil: - return res, err - default: - log.Error("Error fetching header", "err", err) - } - time.Sleep(clientRetryInterval) - } -} - type ServiceConfig struct { - Context context.Context - Metrics *metrics.Metrics - L2RPC *rpc.Client - L2Client *ethclient.Client - ChainID *big.Int + Context context.Context + Metrics *metrics.Metrics + L2RPC *rpc.Client + L2Client *ethclient.Client + ChainID *big.Int + ConfDepth uint64 MaxHeaderBatchSize uint64 StartBlockNumber uint64 - StartBlockHash string DB *db.Database + Bedrock bool } type Service struct { @@ -113,7 +96,7 @@ func NewService(cfg ServiceConfig) (*Service, error) { cfg.ChainID = chainID } - bridges, err := bridge.BridgesByChainID(cfg.ChainID, cfg.L2Client, ctx) + bridges, err := bridge.BridgesByChainID(cfg.ChainID, cfg.L2Client, cfg.Bedrock) if err != nil { cancel() return nil, err @@ -131,7 +114,7 @@ func NewService(cfg ServiceConfig) (*Service, error) { return nil, err } - return &Service{ + service := &Service{ cfg: cfg, ctx: ctx, cancel: cancel, @@ -139,14 +122,18 @@ func NewService(cfg ServiceConfig) (*Service, error) { headerSelector: confirmedHeaderSelector, metrics: cfg.Metrics, tokenCache: map[common.Address]*db.Token{ - db.ETHL2Address: db.ETHL1Token, + predeploys.LegacyERC20ETHAddr: db.ETHL1Token, }, - }, nil + } + service.wg.Add(1) + return service, nil } -func (s *Service) Loop(ctx context.Context) { +func (s *Service) loop() { + defer s.wg.Done() + for { - err := s.catchUp(ctx) + err := s.catchUp() if err == nil { break } @@ -160,10 +147,18 @@ func (s *Service) Loop(ctx context.Context) { } newHeads := make(chan *types.Header, 1000) - go s.subscribeNewHeads(ctx, newHeads) + tick := time.NewTicker(5 * time.Second) + defer tick.Stop() for { select { + case <-tick.C: + header, err := query.HeaderByNumberWithRetry(s.ctx, s.cfg.L2Client) + if err != nil { + logger.Error("error fetching header by number", "err", err) + continue + } + newHeads <- header case header := <-newHeads: logger.Info("Received new header", "header", header.Hash) for { @@ -176,6 +171,7 @@ func (s *Service) Loop(ctx context.Context) { } } case <-s.ctx.Done(): + logger.Info("service stopped") return } } @@ -184,7 +180,6 @@ func (s *Service) Loop(ctx context.Context) { func (s *Service) Update(newHeader *types.Header) error { var lowest = db.BlockLocator{ Number: s.cfg.StartBlockNumber, - Hash: common.HexToHash(s.cfg.StartBlockHash), } highestConfirmed, err := s.cfg.DB.GetHighestL2Block() if err != nil { @@ -209,7 +204,7 @@ func (s *Service) Update(newHeader *types.Header) error { return nil } - if lowest.Hash != headers[0].ParentHash { + if lowest.Number > 0 && lowest.Hash != headers[0].ParentHash { logger.Error("Parent hash does not connect to ", "block", headers[0].Number.Uint64(), "hash", headers[0].Hash(), "lowest_block", lowest.Number, "hash", lowest.Hash) @@ -218,7 +213,6 @@ func (s *Service) Update(newHeader *types.Header) error { startHeight := headers[0].Number.Uint64() endHeight := headers[len(headers)-1].Number.Uint64() - depositsByBlockHash := make(map[common.Hash][]db.Deposit) withdrawalsByBlockHash := make(map[common.Hash][]db.Withdrawal) start := prometheus.NewTimer(s.metrics.UpdateDuration.WithLabelValues("l2")) @@ -227,21 +221,12 @@ func (s *Service) Update(newHeader *types.Header) error { logger.Info("updated index", "start_height", startHeight, "end_height", endHeight, "duration", dur) }() - bridgeDepositsCh := make(chan bridge.DepositsMap, len(s.bridges)) bridgeWdsCh := make(chan bridge.WithdrawalsMap) errCh := make(chan error, len(s.bridges)) for _, bridgeImpl := range s.bridges { go func(b bridge.Bridge) { - deposits, err := b.GetDepositsByBlockRange(startHeight, endHeight) - if err != nil { - errCh <- err - return - } - bridgeDepositsCh <- deposits - }(bridgeImpl) - go func(b bridge.Bridge) { - wds, err := b.GetWithdrawalsByBlockRange(startHeight, endHeight) + wds, err := b.GetWithdrawalsByBlockRange(s.ctx, startHeight, endHeight) if err != nil { errCh <- err return @@ -256,29 +241,19 @@ func (s *Service) Update(newHeader *types.Header) error { case bridgeWds := <-bridgeWdsCh: for blockHash, withdrawals := range bridgeWds { for _, wd := range withdrawals { - if err := s.cacheToken(wd.L2Token); err != nil { + if err := s.cacheToken(wd); err != nil { logger.Warn("error caching token", "err", err) } } withdrawalsByBlockHash[blockHash] = append(withdrawalsByBlockHash[blockHash], withdrawals...) } - case bridgeDeposits := <-bridgeDepositsCh: - for blockHash, deposits := range bridgeDeposits { - for _, deposit := range deposits { - if err := s.cacheToken(deposit.L2Token); err != nil { - logger.Warn("error caching token", "err", err) - } - } - - depositsByBlockHash[blockHash] = append(depositsByBlockHash[blockHash], deposits...) - } case err := <-errCh: return err } receives++ - if receives == 2*len(s.bridges) { + if receives == len(s.bridges) { break } } @@ -286,7 +261,6 @@ func (s *Service) Update(newHeader *types.Header) error { for i, header := range headers { blockHash := header.Hash() number := header.Number.Uint64() - deposits := depositsByBlockHash[blockHash] withdrawals := withdrawalsByBlockHash[blockHash] if len(withdrawals) == 0 && i != len(headers)-1 { @@ -298,7 +272,6 @@ func (s *Service) Update(newHeader *types.Header) error { ParentHash: header.ParentHash, Number: number, Timestamp: header.Time, - Deposits: deposits, Withdrawals: withdrawals, } @@ -358,16 +331,21 @@ func (s *Service) GetIndexerStatus(w http.ResponseWriter, r *http.Request) { server.RespondWithJSON(w, http.StatusOK, status) } -func (s *Service) GetWithdrawalStatus(w http.ResponseWriter, r *http.Request) { +func (s *Service) GetWithdrawalBatch(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) + hash := vars["hash"] + if hash == "" { + server.RespondWithError(w, http.StatusBadRequest, "must specify a hash") + return + } - withdrawal, err := s.cfg.DB.GetWithdrawalStatus(common.HexToHash(vars["hash"])) + batch, err := s.cfg.DB.GetWithdrawalBatch(common.HexToHash(vars["hash"])) if err != nil { server.RespondWithError(w, http.StatusInternalServerError, err.Error()) return } - server.RespondWithJSON(w, http.StatusOK, withdrawal) + server.RespondWithJSON(w, http.StatusOK, batch) } func (s *Service) GetWithdrawals(w http.ResponseWriter, r *http.Request) { @@ -390,12 +368,14 @@ func (s *Service) GetWithdrawals(w http.ResponseWriter, r *http.Request) { return } + finalizationState := db.ParseFinalizationState(r.URL.Query().Get("finalized")) + page := db.PaginationParam{ - Limit: uint64(limit), - Offset: uint64(offset), + Limit: limit, + Offset: offset, } - withdrawals, err := s.cfg.DB.GetWithdrawalsByAddress(common.HexToAddress(vars["address"]), page) + withdrawals, err := s.cfg.DB.GetWithdrawalsByAddress(common.HexToAddress(vars["address"]), page, finalizationState) if err != nil { server.RespondWithError(w, http.StatusInternalServerError, err.Error()) return @@ -404,25 +384,8 @@ func (s *Service) GetWithdrawals(w http.ResponseWriter, r *http.Request) { server.RespondWithJSON(w, http.StatusOK, withdrawals) } -func (s *Service) subscribeNewHeads(ctx context.Context, heads chan *types.Header) { - tick := time.NewTicker(5 * time.Second) - - for { - select { - case <-tick.C: - header, err := HeaderByNumberWithRetry(ctx, s.cfg.L2Client) - if err != nil { - logger.Error("error fetching header by number", "err", err) - } - heads <- header - case <-ctx.Done(): - return - } - } -} - -func (s *Service) catchUp(ctx context.Context) error { - realHead, err := HeaderByNumberWithRetry(ctx, s.cfg.L2Client) +func (s *Service) catchUp() error { + realHead, err := query.HeaderByNumberWithRetry(s.ctx, s.cfg.L2Client) if err != nil { return err } @@ -446,8 +409,8 @@ func (s *Service) catchUp(ctx context.Context) error { for realHeadNum-s.cfg.ConfDepth > currHeadNum+s.cfg.MaxHeaderBatchSize { select { - case <-ctx.Done(): - return context.Canceled + case <-s.ctx.Done(): + return s.ctx.Err() default: if err := s.Update(realHead); err != nil && err != errNoNewBlocks { return err @@ -465,32 +428,32 @@ func (s *Service) catchUp(ctx context.Context) error { return nil } -func (s *Service) cacheToken(address common.Address) error { - if s.tokenCache[address] != nil { +func (s *Service) cacheToken(withdrawal db.Withdrawal) error { + if s.tokenCache[withdrawal.L2Token] != nil { return nil } - token, err := s.cfg.DB.GetL2TokenByAddress(address.String()) + token, err := s.cfg.DB.GetL2TokenByAddress(withdrawal.L2Token.String()) if err != nil { return err } if token != nil { s.metrics.IncL2CachedTokensCount() - s.tokenCache[address] = token + s.tokenCache[withdrawal.L2Token] = token return nil } - token, err = QueryERC20(address, s.cfg.L2Client) + token, err = query.NewERC20(withdrawal.L2Token, s.cfg.L2Client) if err != nil { logger.Error("Error querying ERC20 token details", - "l2_token", address.String(), "err", err) + "l2_token", withdrawal.L2Token.String(), "err", err) token = &db.Token{ - Address: address.String(), + Address: withdrawal.L2Token.String(), } } - if err := s.cfg.DB.AddL2Token(address.String(), token); err != nil { + if err := s.cfg.DB.AddL2Token(withdrawal.L2Token.String(), token); err != nil { return err } - s.tokenCache[address] = token + s.tokenCache[withdrawal.L2Token] = token s.metrics.IncL2CachedTokensCount() return nil } @@ -499,16 +462,11 @@ func (s *Service) Start() error { if s.cfg.ChainID == nil { return errNoChainID } - s.wg.Add(1) - go s.Loop(s.ctx) + go s.loop() return nil } func (s *Service) Stop() { s.cancel() s.wg.Wait() - err := s.cfg.DB.Close() - if err != nil { - logger.Error("Error closing db", "err", err) - } } diff --git a/indexer/services/l2/query.go b/indexer/services/query/erc20.go similarity index 87% rename from indexer/services/l2/query.go rename to indexer/services/query/erc20.go index 4e5d65f1f799b..5b2a793495dbd 100644 --- a/indexer/services/l2/query.go +++ b/indexer/services/query/erc20.go @@ -1,15 +1,14 @@ -package l2 +package query import ( "github.com/ethereum-optimism/optimism/indexer/db" - "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" ) -func QueryERC20(address common.Address, client *ethclient.Client) (*db.Token, error) { +func NewERC20(address common.Address, client *ethclient.Client) (*db.Token, error) { contract, err := bindings.NewERC20(address, client) if err != nil { return nil, err diff --git a/indexer/services/query/headers.go b/indexer/services/query/headers.go new file mode 100644 index 0000000000000..52c1e7e3e34c8 --- /dev/null +++ b/indexer/services/query/headers.go @@ -0,0 +1,20 @@ +package query + +import ( + "context" + + "github.com/ethereum-optimism/optimism/op-service/backoff" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +// HeaderByNumberWithRetry retries getting headers. +func HeaderByNumberWithRetry(ctx context.Context, client *ethclient.Client) (*types.Header, error) { + var res *types.Header + err := backoff.DoCtx(ctx, 3, backoff.Exponential(), func() error { + var err error + res, err = client.HeaderByNumber(ctx, nil) + return err + }) + return res, err +} diff --git a/integration-tests/test/nft-bridge.spec.ts b/integration-tests/test/nft-bridge.spec.ts index 0640d97d8ae51..83e395ab06d07 100644 --- a/integration-tests/test/nft-bridge.spec.ts +++ b/integration-tests/test/nft-bridge.spec.ts @@ -113,12 +113,11 @@ describe('ERC721 Bridge', () => { ) // Create a L2 Standard ERC721 with the Standard ERC721 Factory - const tx = - await OptimismMintableERC721Factory.createStandardOptimismMintableERC721( - L1ERC721.address, - 'L2ERC721', - 'L2' - ) + const tx = await OptimismMintableERC721Factory.createOptimismMintableERC721( + L1ERC721.address, + 'L2ERC721', + 'L2' + ) const receipt = await tx.wait() // Get the OptimismMintableERC721Created event diff --git a/l2geth/cmd/geth/main.go b/l2geth/cmd/geth/main.go index 57af9c98d4b70..bdc6a84a07ffd 100644 --- a/l2geth/cmd/geth/main.go +++ b/l2geth/cmd/geth/main.go @@ -188,6 +188,7 @@ var ( utils.IPCPathFlag, utils.InsecureUnlockAllowedFlag, utils.RPCGlobalGasCap, + utils.RPCGlobalEVMTimeoutFlag, } whisperFlags = []cli.Flag{ diff --git a/l2geth/cmd/geth/usage.go b/l2geth/cmd/geth/usage.go index 8a8a55bce4836..5e91377c8a14a 100644 --- a/l2geth/cmd/geth/usage.go +++ b/l2geth/cmd/geth/usage.go @@ -178,6 +178,7 @@ var AppHelpFlagGroups = []flagGroup{ utils.RPCPortFlag, utils.RPCApiFlag, utils.RPCGlobalGasCap, + utils.RPCGlobalEVMTimeoutFlag, utils.RPCCORSDomainFlag, utils.RPCVirtualHostsFlag, utils.WSEnabledFlag, diff --git a/l2geth/cmd/utils/flags.go b/l2geth/cmd/utils/flags.go index 2747673fc0fcb..27c838fa0267c 100644 --- a/l2geth/cmd/utils/flags.go +++ b/l2geth/cmd/utils/flags.go @@ -518,6 +518,11 @@ var ( Name: "rpc.gascap", Usage: "Sets a cap on gas that can be used in eth_call/estimateGas", } + RPCGlobalEVMTimeoutFlag = &cli.DurationFlag{ + Name: "rpc.evmtimeout", + Usage: "Sets a timeout used for eth_call (0=infinite)", + Value: eth.DefaultConfig.RPCEVMTimeout, + } // Logging and debug settings EthStatsURLFlag = cli.StringFlag{ Name: "ethstats", @@ -1660,6 +1665,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { if ctx.GlobalIsSet(RPCGlobalGasCap.Name) { cfg.RPCGasCap = new(big.Int).SetUint64(ctx.GlobalUint64(RPCGlobalGasCap.Name)) } + if ctx.GlobalIsSet(RPCGlobalEVMTimeoutFlag.Name) { + cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name) + } // Override any default configs for hard coded networks. switch { diff --git a/l2geth/eth/api_backend.go b/l2geth/eth/api_backend.go index 35de825c9757b..247ef73bd3843 100644 --- a/l2geth/eth/api_backend.go +++ b/l2geth/eth/api_backend.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "math/big" + "time" "github.com/ethereum-optimism/optimism/l2geth/accounts" "github.com/ethereum-optimism/optimism/l2geth/common" @@ -400,6 +401,10 @@ func (b *EthAPIBackend) RPCGasCap() *big.Int { return b.eth.config.RPCGasCap } +func (b *EthAPIBackend) RPCEVMTimeout() time.Duration { + return b.eth.config.RPCEVMTimeout +} + func (b *EthAPIBackend) BloomStatus() (uint64, uint64) { sections, _, _ := b.eth.bloomIndexer.Sections() return params.BloomBitsBlocks, sections diff --git a/l2geth/eth/config.go b/l2geth/eth/config.go index a1f84bf2f71a2..9f0c853800170 100644 --- a/l2geth/eth/config.go +++ b/l2geth/eth/config.go @@ -57,7 +57,8 @@ var DefaultConfig = Config{ GasPrice: big.NewInt(params.GWei), Recommit: 3 * time.Second, }, - TxPool: core.DefaultTxPoolConfig, + TxPool: core.DefaultTxPoolConfig, + RPCEVMTimeout: 5 * time.Second, GPO: gasprice.Config{ Blocks: 20, Percentile: 60, @@ -169,6 +170,9 @@ type Config struct { // RPCGasCap is the global gas cap for eth-call variants. RPCGasCap *big.Int `toml:",omitempty"` + // RPCEVMTimeout is the global timeout for eth-call. (0=infinite) + RPCEVMTimeout time.Duration + // Checkpoint is a hardcoded checkpoint which can be nil. Checkpoint *params.TrustedCheckpoint `toml:",omitempty"` diff --git a/l2geth/graphql/graphql.go b/l2geth/graphql/graphql.go index 730a0a5ef0084..b3039f5e08c79 100644 --- a/l2geth/graphql/graphql.go +++ b/l2geth/graphql/graphql.go @@ -20,7 +20,6 @@ package graphql import ( "context" "errors" - "time" ethereum "github.com/ethereum-optimism/optimism/l2geth" "github.com/ethereum-optimism/optimism/l2geth/common" @@ -776,7 +775,7 @@ func (b *Block) Call(ctx context.Context, args struct { return nil, err } } - result, gas, failed, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, &vm.Config{}, 5*time.Second, b.backend.RPCGasCap()) + result, gas, failed, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, &vm.Config{}, b.backend.RPCEVMTimeout(), b.backend.RPCGasCap()) status := hexutil.Uint64(1) if failed { status = 0 @@ -842,7 +841,7 @@ func (p *Pending) Call(ctx context.Context, args struct { Data ethapi.CallArgs }) (*CallResult, error) { pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) - result, gas, failed, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, &vm.Config{}, 5*time.Second, p.backend.RPCGasCap()) + result, gas, failed, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, &vm.Config{}, p.backend.RPCEVMTimeout(), p.backend.RPCGasCap()) status := hexutil.Uint64(1) if failed { status = 0 diff --git a/l2geth/internal/ethapi/api.go b/l2geth/internal/ethapi/api.go index c009509c2c9cd..64b736b008b73 100644 --- a/l2geth/internal/ethapi/api.go +++ b/l2geth/internal/ethapi/api.go @@ -963,7 +963,7 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNrOr if overrides != nil { accounts = *overrides } - result, _, failed, err := DoCall(ctx, s.b, args, blockNrOrHash, accounts, &vm.Config{}, 5*time.Second, s.b.RPCGasCap()) + result, _, failed, err := DoCall(ctx, s.b, args, blockNrOrHash, accounts, &vm.Config{}, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) if err != nil { return nil, err } diff --git a/l2geth/internal/ethapi/backend.go b/l2geth/internal/ethapi/backend.go index ca2f40098dbfa..d2a8d33c30212 100644 --- a/l2geth/internal/ethapi/backend.go +++ b/l2geth/internal/ethapi/backend.go @@ -20,6 +20,7 @@ package ethapi import ( "context" "math/big" + "time" "github.com/ethereum-optimism/optimism/l2geth/accounts" "github.com/ethereum-optimism/optimism/l2geth/common" @@ -45,7 +46,8 @@ type Backend interface { ChainDb() ethdb.Database AccountManager() *accounts.Manager ExtRPCEnabled() bool - RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection + RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection + RPCEVMTimeout() time.Duration // global timeout (0=infinite) for eth_call over rpc: DoS protection // Blockchain API SetHead(number uint64) diff --git a/l2geth/les/api_backend.go b/l2geth/les/api_backend.go index 98e2360be3642..13e899ecce106 100644 --- a/l2geth/les/api_backend.go +++ b/l2geth/les/api_backend.go @@ -20,6 +20,7 @@ import ( "context" "errors" "math/big" + "time" "github.com/ethereum-optimism/optimism/l2geth/accounts" "github.com/ethereum-optimism/optimism/l2geth/common" @@ -316,6 +317,10 @@ func (b *LesApiBackend) RPCGasCap() *big.Int { return b.eth.config.RPCGasCap } +func (b *LesApiBackend) RPCEVMTimeout() time.Duration { + return b.eth.config.RPCEVMTimeout +} + func (b *LesApiBackend) BloomStatus() (uint64, uint64) { if b.eth.bloomIndexer == nil { return 0, 0 diff --git a/op-batcher/batch_submitter.go b/op-batcher/batch_submitter.go index fd935b86ab1a3..67168af40d072 100644 --- a/op-batcher/batch_submitter.go +++ b/op-batcher/batch_submitter.go @@ -16,18 +16,16 @@ import ( "syscall" "time" + "github.com/ethereum-optimism/optimism/op-batcher/sequencer" + "github.com/ethereum-optimism/optimism/op-node/client" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/sources" + "github.com/ethereum-optimism/optimism/op-proposer/txmgr" oplog "github.com/ethereum-optimism/optimism/op-service/log" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" oppprof "github.com/ethereum-optimism/optimism/op-service/pprof" oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" - hdwallet "github.com/miguelmota/go-ethereum-hdwallet" - "github.com/urfave/cli" - - "github.com/ethereum-optimism/optimism/op-batcher/sequencer" - "github.com/ethereum-optimism/optimism/op-node/eth" - "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum-optimism/optimism/op-proposer/txmgr" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -36,6 +34,8 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" + hdwallet "github.com/miguelmota/go-ethereum-hdwallet" + "github.com/urfave/cli" ) const ( @@ -94,6 +94,7 @@ func Main(version string) func(cliCtx *cli.Context) error { l.Error("error starting metrics server", err) } }() + opmetrics.LaunchBalanceMetrics(ctx, l, registry, "", batchSubmitter.cfg.L1Client, batchSubmitter.addr) } rpcCfg := cfg.RPCConfig @@ -125,6 +126,7 @@ func Main(version string) func(cliCtx *cli.Context) error { // batches to L1 for availability. type BatchSubmitter struct { txMgr txmgr.TxManager + addr common.Address cfg sequencer.Config wg sync.WaitGroup done chan struct{} @@ -244,6 +246,7 @@ func NewBatchSubmitter(cfg Config, l log.Logger) (*BatchSubmitter, error) { return &BatchSubmitter{ cfg: batcherCfg, + addr: addr, txMgr: txmgr.NewSimpleTxManager("batcher", txManagerConfig, l1Client), done: make(chan struct{}), log: l, @@ -495,12 +498,12 @@ func dialRollupClientWithTimeout(ctx context.Context, url string) (*sources.Roll ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout) defer cancel() - client, err := rpc.DialContext(ctxt, url) + rpcCl, err := rpc.DialContext(ctxt, url) if err != nil { return nil, err } - return sources.NewRollupClient(client), nil + return sources.NewRollupClient(client.NewBaseRPCClient(rpcCl)), nil } // parseAddress parses an ETH address from a hex string. This method will fail if diff --git a/op-batcher/go.mod b/op-batcher/go.mod index 6798194232c4f..ab2dec2f8f1dc 100644 --- a/op-batcher/go.mod +++ b/op-batcher/go.mod @@ -3,9 +3,9 @@ module github.com/ethereum-optimism/optimism/op-batcher go 1.18 require ( - github.com/ethereum-optimism/optimism/op-node v0.8.8 - github.com/ethereum-optimism/optimism/op-proposer v0.8.8 - github.com/ethereum-optimism/optimism/op-service v0.8.8 + github.com/ethereum-optimism/optimism/op-node v0.8.10 + github.com/ethereum-optimism/optimism/op-proposer v0.8.10 + github.com/ethereum-optimism/optimism/op-service v0.8.10 github.com/ethereum/go-ethereum v1.10.23 github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/urfave/cli v1.22.9 @@ -22,7 +22,7 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/deckarep/golang-set v1.8.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/ethereum-optimism/optimism/op-bindings v0.8.8 // indirect + github.com/ethereum-optimism/optimism/op-bindings v0.8.10 // indirect github.com/fjl/memsize v0.0.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-stack/stack v1.8.1 // indirect diff --git a/op-batcher/go.sum b/op-batcher/go.sum index 32cf7d12a4c21..ff187d59f71a3 100644 --- a/op-batcher/go.sum +++ b/op-batcher/go.sum @@ -149,14 +149,14 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd h1:NchOnosWOkH9wlix8QevGHE+6vuRa+OMGvDNsczv2kQ= github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8 h1:HN625JI2VsRsli+U6GAXipg7lAKx8EOmGIovN79Az+I= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= -github.com/ethereum-optimism/optimism/op-node v0.8.8 h1:WuZF1RsZnB+u/wwWToVaC1lZWfGfgncLusUssA3Hm+o= -github.com/ethereum-optimism/optimism/op-node v0.8.8/go.mod h1:O5nXPCx8vn9c/CHgBC7vP5utcanIQ4uhWKkJ3pAaaSQ= -github.com/ethereum-optimism/optimism/op-proposer v0.8.8 h1:IV0P64q7RJ52yvLMBLAKyqeDOxdQPGHbhmIXGkMKG/8= -github.com/ethereum-optimism/optimism/op-proposer v0.8.8/go.mod h1:PSNjVKZQxjlkDTcXnoCt3Aeo6N6nY0Ma+R+ZHOTsXU8= -github.com/ethereum-optimism/optimism/op-service v0.8.8 h1:k5E78Zr2cGU0SwjoHpFXuC1eyfXhu3oKEOnDDaFi57I= -github.com/ethereum-optimism/optimism/op-service v0.8.8/go.mod h1:K0uybOhICTc2yfhrRj0cD1m7aPkOf5C9e6bUmvf4rGA= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10 h1:aSAWCQwBQnbmv03Gvtuvn3qfTWrZu/sTlRAWrpQhiHc= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= +github.com/ethereum-optimism/optimism/op-node v0.8.10 h1:1Gc4FtR5B+HgfQ+byNn3P+tiJarpMZSYjj5iLvA3YtU= +github.com/ethereum-optimism/optimism/op-node v0.8.10/go.mod h1:6NkgIThuQbPY6fA9lI2A52DaeLM2FvrcwGCBVEY2fS8= +github.com/ethereum-optimism/optimism/op-proposer v0.8.10 h1:dLzbYmaoMBViqCPlIUFB+bagSuwsd173P8kDhUMbBTQ= +github.com/ethereum-optimism/optimism/op-proposer v0.8.10/go.mod h1:tdUw40bNis2G1uDT3jNv7BWWM+FzTar+fS5zv6o2YPA= +github.com/ethereum-optimism/optimism/op-service v0.8.10 h1:K3IABHI1b0MDrDXALvTKTbzy6IogGD6NgmbqfKEcEwM= +github.com/ethereum-optimism/optimism/op-service v0.8.10/go.mod h1:K0uybOhICTc2yfhrRj0cD1m7aPkOf5C9e6bUmvf4rGA= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= diff --git a/op-bindings/bindings/deployerwhitelist_more.go b/op-bindings/bindings/deployerwhitelist_more.go index 360fd037e893a..da378cdf9108f 100644 --- a/op-bindings/bindings/deployerwhitelist_more.go +++ b/op-bindings/bindings/deployerwhitelist_more.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const DeployerWhitelistStorageLayoutJSON = "{\"storage\":[{\"astId\":2853,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":2858,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"whitelist\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_bool\"}}}" +const DeployerWhitelistStorageLayoutJSON = "{\"storage\":[{\"astId\":2850,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":2855,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"whitelist\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_bool\"}}}" var DeployerWhitelistStorageLayout = new(solc.StorageLayout) diff --git a/op-bindings/bindings/gaspriceoracle_more.go b/op-bindings/bindings/gaspriceoracle_more.go index 0c53aa7cd0134..e6600efab4b49 100644 --- a/op-bindings/bindings/gaspriceoracle_more.go +++ b/op-bindings/bindings/gaspriceoracle_more.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const GasPriceOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":27735,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1754,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer_1_0_32\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":1757,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer_2_0_32\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":1760,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"overhead\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint256\"},{\"astId\":1763,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"scalar\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_uint256\"},{\"astId\":1766,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"decimals\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_uint256\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" +const GasPriceOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":27823,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1751,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer_1_0_32\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":1754,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer_2_0_32\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":1757,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"overhead\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint256\"},{\"astId\":1760,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"scalar\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_uint256\"},{\"astId\":1763,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"decimals\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_uint256\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" var GasPriceOracleStorageLayout = new(solc.StorageLayout) diff --git a/op-bindings/bindings/governancetoken_more.go b/op-bindings/bindings/governancetoken_more.go index 671f707cbcc03..33c56aa550c2b 100644 --- a/op-bindings/bindings/governancetoken_more.go +++ b/op-bindings/bindings/governancetoken_more.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const GovernanceTokenStorageLayoutJSON = "{\"storage\":[{\"astId\":27934,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":27940,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":27942,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":27944,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":27946,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":29311,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_nonces\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_mapping(t_address,t_struct(Counter)30100_storage)\"},{\"astId\":29319,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_PERMIT_TYPEHASH_DEPRECATED_SLOT\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_bytes32\"},{\"astId\":28652,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_delegates\",\"offset\":0,\"slot\":\"7\",\"type\":\"t_mapping(t_address,t_address)\"},{\"astId\":28658,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_checkpoints\",\"offset\":0,\"slot\":\"8\",\"type\":\"t_mapping(t_address,t_array(t_struct(Checkpoint)28643_storage)dyn_storage)\"},{\"astId\":28662,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_totalSupplyCheckpoints\",\"offset\":0,\"slot\":\"9\",\"type\":\"t_array(t_struct(Checkpoint)28643_storage)dyn_storage\"},{\"astId\":27735,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"10\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_struct(Checkpoint)28643_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct ERC20Votes.Checkpoint[]\",\"numberOfBytes\":\"32\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_address,t_address)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e address)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_address\"},\"t_mapping(t_address,t_array(t_struct(Checkpoint)28643_storage)dyn_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e struct ERC20Votes.Checkpoint[])\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_array(t_struct(Checkpoint)28643_storage)dyn_storage\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_struct(Counter)30100_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e struct Counters.Counter)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_struct(Counter)30100_storage\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_struct(Checkpoint)28643_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ERC20Votes.Checkpoint\",\"numberOfBytes\":\"32\"},\"t_struct(Counter)30100_storage\":{\"encoding\":\"inplace\",\"label\":\"struct Counters.Counter\",\"numberOfBytes\":\"32\"},\"t_uint224\":{\"encoding\":\"inplace\",\"label\":\"uint224\",\"numberOfBytes\":\"28\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint32\":{\"encoding\":\"inplace\",\"label\":\"uint32\",\"numberOfBytes\":\"4\"}}}" +const GovernanceTokenStorageLayoutJSON = "{\"storage\":[{\"astId\":28173,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":28179,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":28181,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":28183,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":28185,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":29550,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_nonces\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_mapping(t_address,t_struct(Counter)30339_storage)\"},{\"astId\":29558,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_PERMIT_TYPEHASH_DEPRECATED_SLOT\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_bytes32\"},{\"astId\":28891,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_delegates\",\"offset\":0,\"slot\":\"7\",\"type\":\"t_mapping(t_address,t_address)\"},{\"astId\":28897,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_checkpoints\",\"offset\":0,\"slot\":\"8\",\"type\":\"t_mapping(t_address,t_array(t_struct(Checkpoint)28882_storage)dyn_storage)\"},{\"astId\":28901,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_totalSupplyCheckpoints\",\"offset\":0,\"slot\":\"9\",\"type\":\"t_array(t_struct(Checkpoint)28882_storage)dyn_storage\"},{\"astId\":27823,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"10\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_struct(Checkpoint)28882_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct ERC20Votes.Checkpoint[]\",\"numberOfBytes\":\"32\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_address,t_address)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e address)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_address\"},\"t_mapping(t_address,t_array(t_struct(Checkpoint)28882_storage)dyn_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e struct ERC20Votes.Checkpoint[])\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_array(t_struct(Checkpoint)28882_storage)dyn_storage\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_struct(Counter)30339_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e struct Counters.Counter)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_struct(Counter)30339_storage\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_struct(Checkpoint)28882_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ERC20Votes.Checkpoint\",\"numberOfBytes\":\"32\"},\"t_struct(Counter)30339_storage\":{\"encoding\":\"inplace\",\"label\":\"struct Counters.Counter\",\"numberOfBytes\":\"32\"},\"t_uint224\":{\"encoding\":\"inplace\",\"label\":\"uint224\",\"numberOfBytes\":\"28\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint32\":{\"encoding\":\"inplace\",\"label\":\"uint32\",\"numberOfBytes\":\"4\"}}}" var GovernanceTokenStorageLayout = new(solc.StorageLayout) diff --git a/op-bindings/bindings/l1block_more.go b/op-bindings/bindings/l1block_more.go index 9e1e866cf2af4..9dcd457d70cfa 100644 --- a/op-bindings/bindings/l1block_more.go +++ b/op-bindings/bindings/l1block_more.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const L1BlockStorageLayoutJSON = "{\"storage\":[{\"astId\":2101,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"number\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint64\"},{\"astId\":2104,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"timestamp\",\"offset\":8,\"slot\":\"0\",\"type\":\"t_uint64\"},{\"astId\":2107,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"basefee\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":2110,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"hash\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_bytes32\"},{\"astId\":2113,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"sequenceNumber\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint64\"}],\"types\":{\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"}}}" +const L1BlockStorageLayoutJSON = "{\"storage\":[{\"astId\":2098,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"number\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint64\"},{\"astId\":2101,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"timestamp\",\"offset\":8,\"slot\":\"0\",\"type\":\"t_uint64\"},{\"astId\":2104,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"basefee\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":2107,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"hash\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_bytes32\"},{\"astId\":2110,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"sequenceNumber\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint64\"}],\"types\":{\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"}}}" var L1BlockStorageLayout = new(solc.StorageLayout) diff --git a/op-bindings/bindings/l1crossdomainmessenger.go b/op-bindings/bindings/l1crossdomainmessenger.go index 4d3cb89c1928f..7fca6fc921ab6 100644 --- a/op-bindings/bindings/l1crossdomainmessenger.go +++ b/op-bindings/bindings/l1crossdomainmessenger.go @@ -30,8 +30,8 @@ var ( // L1CrossDomainMessengerMetaData contains all meta data concerning the L1CrossDomainMessenger contract. var L1CrossDomainMessengerMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractOptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"FailedRelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"RelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"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\"}],\"name\":\"SentMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SentMessageExtension1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherMessenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"portal\",\"outputs\":[{\"internalType\":\"contractOptimismPortal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"receivedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"relayMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"sendMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b50604051620029413803806200294183398101604081905262000035916200045b565b734200000000000000000000000000000000000007608052600060a081905260c052600160e0526001600160a01b03811661010052620000746200007b565b506200048d565b600054600160a81b900460ff1615808015620000a457506000546001600160a01b90910460ff16105b80620000db5750620000c130620001c860201b6200125d1760201c565b158015620000db5750600054600160a01b900460ff166001145b620001445760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000172576000805460ff60a81b1916600160a81b1790555b6200017c620001d7565b8015620001c5576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002355760405162461bcd60e51b815260206004820152602b60248201526000805160206200292183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b60cc80546001600160a01b03191661dead1790556200025362000273565b6200025d620002d1565b620002676200033a565b62000271620003a4565b565b600054600160a81b900460ff16620002715760405162461bcd60e51b815260206004820152602b60248201526000805160206200292183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b600054600160a81b900460ff166200032f5760405162461bcd60e51b815260206004820152602b60248201526000805160206200292183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b620002713362000409565b600054600160a81b900460ff16620003985760405162461bcd60e51b815260206004820152602b60248201526000805160206200292183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b6065805460ff19169055565b600054600160a81b900460ff16620004025760405162461bcd60e51b815260206004820152602b60248201526000805160206200292183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b6001609755565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000602082840312156200046e57600080fd5b81516001600160a01b03811681146200048657600080fd5b9392505050565b60805160a05160c05160e05161010051612425620004fc6000396000818161027f015281816112b6015281816117d40152818161183501526119010152600061077d015260006107540152600061072b0152600081816103d1015281816104ad01526117fe01526124256000f3fe6080604052600436106101755760003560e01c80637dea7cc3116100cb578063b28ade251161007f578063ecc7042811610059578063ecc70428146103f3578063f2fde38b14610458578063f69f81511461047857600080fd5b8063b28ade251461038c578063d764ad0b146103ac578063db505d80146103bf57600080fd5b80638456cb59116100b05780638456cb591461031c5780638da5cb5b14610331578063b1b1b2091461035c57600080fd5b80637dea7cc3146102f05780638129fc1c1461030757600080fd5b80633f827a5a1161012d5780636425666b116101075780636425666b1461026d5780636e296e45146102c6578063715018a6146102db57600080fd5b80633f827a5a146101ff57806354fd4d50146102275780635c975abb1461024957600080fd5b80632828d7e81161015e5780632828d7e8146101bf5780633dbb202b146101d55780633f4ba83a146101ea57600080fd5b8063028f85f71461017a5780630c568498146101a9575b600080fd5b34801561018657600080fd5b5061018f601081565b60405163ffffffff90911681526020015b60405180910390f35b3480156101b557600080fd5b5061018f6103e881565b3480156101cb57600080fd5b5061018f6103f881565b6101e86101e3366004611de4565b6104a8565b005b3480156101f657600080fd5b506101e8610712565b34801561020b57600080fd5b50610214600181565b60405161ffff90911681526020016101a0565b34801561023357600080fd5b5061023c610724565b6040516101a09190611ec5565b34801561025557600080fd5b5060655460ff165b60405190151581526020016101a0565b34801561027957600080fd5b506102a17f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a0565b3480156102d257600080fd5b506102a16107c7565b3480156102e757600080fd5b506101e86108b3565b3480156102fc57600080fd5b5061018f62030d4081565b34801561031357600080fd5b506101e86108c5565b34801561032857600080fd5b506101e8610ac2565b34801561033d57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166102a1565b34801561036857600080fd5b5061025d610377366004611edf565b60cb6020526000908152604090205460ff1681565b34801561039857600080fd5b5061018f6103a7366004611ef8565b610ad2565b6101e86103ba366004611f4c565b610b18565b3480156103cb57600080fd5b506102a17f000000000000000000000000000000000000000000000000000000000000000081565b3480156103ff57600080fd5b5061044a60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a0565b34801561046457600080fd5b506101e8610473366004611fd2565b6111a9565b34801561048457600080fd5b5061025d610493366004611edf565b60ce6020526000908152604090205460ff1681565b6105e77f00000000000000000000000000000000000000000000000000000000000000006104d7858585610ad2565b63ffffffff16347fd764ad0b0000000000000000000000000000000000000000000000000000000061054960cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105659796959493929190612038565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611279565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561066c60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b8660405161067e959493929190612097565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b61071a61132e565b6107226113af565b565b606061074f7f000000000000000000000000000000000000000000000000000000000000000061142c565b6107787f000000000000000000000000000000000000000000000000000000000000000061142c565b6107a17f000000000000000000000000000000000000000000000000000000000000000061142c565b6040516020016107b3939291906120e5565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6108bb61132e565b6107226000611561565b6000547501000000000000000000000000000000000000000000900460ff1615808015610910575060005460017401000000000000000000000000000000000000000090910460ff16105b806109425750303b158015610942575060005474010000000000000000000000000000000000000000900460ff166001145b6109ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161088d565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610a5457600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610a5c6115d8565b8015610abf57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610aca61132e565b6107226116cf565b600062030d40610ae360108561218a565b6103e8610af26103f88661218a565b610afc91906121e5565b610b069190612208565b610b109190612208565b949350505050565b600260975403610b84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161088d565b6002609755610b9161172a565b60f087901c60018114610c4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605560248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2031206d657373616765732061726520737570706f72746564206166746560648201527f722074686520426564726f636b20757067726164650000000000000000000000608482015260a40161088d565b6000610c92898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061179792505050565b9050610c9c6117ba565b15610cb557853414610cb057610cb0612230565b610e07565b3415610d69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161088d565b600081815260ce602052604090205460ff16610e07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161088d565b610e10876118de565b15610ec3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161088d565b600081815260cb602052604090205460ff1615610f62576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161088d565b610f6e61afc88661225f565b5a1015610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a20696e737566666963696560448201527f6e742067617320746f2072656c6179206d657373616765000000000000000000606482015260840161088d565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006110998861105161138861afc8612277565b5a61105c9190612277565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061195592505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560010361113457600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2611193565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a25b505060016097555050505050505050565b905090565b6111b161132e565b73ffffffffffffffffffffffffffffffffffffffff8116611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161088d565b610abf81611561565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c429084906112f690889083908990600090899060040161228e565b6000604051808303818588803b15801561130f57600080fd5b505af1158015611323573d6000803e3d6000fd5b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161088d565b6113b761196f565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60608160000361146f57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156114995780611483816122e6565b91506114929050600a8361231e565b9150611473565b60008167ffffffffffffffff8111156114b4576114b4612332565b6040519080825280601f01601f1916602001820160405280156114de576020820181803683370190505b5090505b8415610b10576114f3600183612277565b9150611500600a86612361565b61150b90603061225f565b60f81b81838151811061152057611520612375565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061155a600a8661231e565b94506114e2565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000547501000000000000000000000000000000000000000000900460ff16611683576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556116b76119db565b6116bf611a86565b6116c7611b3a565b610722611c0f565b6116d761172a565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114023390565b60655460ff1615610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161088d565b60006117a7878787878787611cc1565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156111a457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa15801561189e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c291906123a4565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff821630148061194f57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080600080845160208601878a8af19695505050505050565b60655460ff16610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161088d565b6000547501000000000000000000000000000000000000000000900460ff16610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b6000547501000000000000000000000000000000000000000000900460ff16611b31576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b61072233611561565b6000547501000000000000000000000000000000000000000000900460ff16611be5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000547501000000000000000000000000000000000000000000900460ff16611cba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b6001609755565b6060868686868686604051602401611cde969594939291906123c1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610abf57600080fd5b60008083601f840112611d9457600080fd5b50813567ffffffffffffffff811115611dac57600080fd5b602083019150836020828501011115611dc457600080fd5b9250929050565b803563ffffffff81168114611ddf57600080fd5b919050565b60008060008060608587031215611dfa57600080fd5b8435611e0581611d60565b9350602085013567ffffffffffffffff811115611e2157600080fd5b611e2d87828801611d82565b9094509250611e40905060408601611dcb565b905092959194509250565b60005b83811015611e66578181015183820152602001611e4e565b83811115611e75576000848401525b50505050565b60008151808452611e93816020860160208601611e4b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ed86020830184611e7b565b9392505050565b600060208284031215611ef157600080fd5b5035919050565b600080600060408486031215611f0d57600080fd5b833567ffffffffffffffff811115611f2457600080fd5b611f3086828701611d82565b9094509250611f43905060208501611dcb565b90509250925092565b600080600080600080600060c0888a031215611f6757600080fd5b873596506020880135611f7981611d60565b95506040880135611f8981611d60565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611fb357600080fd5b611fbf8a828b01611d82565b989b979a50959850939692959293505050565b600060208284031215611fe457600080fd5b8135611ed881611d60565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a083015261208a60c083018486611fef565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff861681526080602082015260006120c7608083018688611fef565b905083604083015263ffffffff831660608301529695505050505050565b600084516120f7818460208901611e4b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612133816001850160208a01611e4b565b6001920191820152835161214e816002840160208801611e4b565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818516818304811182151516156121ad576121ad61215b565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600063ffffffff808416806121fc576121fc6121b6565b92169190910492915050565b600063ffffffff8083168185168083038211156122275761222761215b565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082198211156122725761227261215b565b500190565b6000828210156122895761228961215b565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a0608082015260006122db60a0830184611e7b565b979650505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123175761231761215b565b5060010190565b60008261232d5761232d6121b6565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082612370576123706121b6565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123b657600080fd5b8151611ed881611d60565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261240c60c0830184611e7b565b9897505050505050505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + ABI: "[{\"inputs\":[{\"internalType\":\"contractOptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"FailedRelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"RelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"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\"}],\"name\":\"SentMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SentMessageExtension1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherMessenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"portal\",\"outputs\":[{\"internalType\":\"contractOptimismPortal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"receivedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"relayMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"sendMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b50604051620029513803806200295183398101604081905262000035916200045b565b734200000000000000000000000000000000000007608052600060a081905260c052600160e0526001600160a01b03811661010052620000746200007b565b506200048d565b600054600160a81b900460ff1615808015620000a457506000546001600160a01b90910460ff16105b80620000db5750620000c130620001c860201b620012611760201c565b158015620000db5750600054600160a01b900460ff166001145b620001445760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000172576000805460ff60a81b1916600160a81b1790555b6200017c620001d7565b8015620001c5576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002355760405162461bcd60e51b815260206004820152602b60248201526000805160206200293183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b60cc80546001600160a01b03191661dead1790556200025362000273565b6200025d620002d1565b620002676200033a565b62000271620003a4565b565b600054600160a81b900460ff16620002715760405162461bcd60e51b815260206004820152602b60248201526000805160206200293183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b600054600160a81b900460ff166200032f5760405162461bcd60e51b815260206004820152602b60248201526000805160206200293183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b620002713362000409565b600054600160a81b900460ff16620003985760405162461bcd60e51b815260206004820152602b60248201526000805160206200293183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b6065805460ff19169055565b600054600160a81b900460ff16620004025760405162461bcd60e51b815260206004820152602b60248201526000805160206200293183398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b6001609755565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000602082840312156200046e57600080fd5b81516001600160a01b03811681146200048657600080fd5b9392505050565b60805160a05160c05160e05161010051612435620004fc60003960008181610283015281816112ba015281816117d80152818161183901526119050152600061077b01526000610752015260006107290152600081816103d5015281816104b1015261180201526124356000f3fe6080604052600436106101755760003560e01c80637dea7cc3116100cb578063b28ade251161007f578063ecc7042811610059578063ecc70428146103f7578063f2fde38b1461045c578063f69f81511461047c57600080fd5b8063b28ade2514610390578063d764ad0b146103b0578063db505d80146103c357600080fd5b80638456cb59116100b05780638456cb59146103205780638da5cb5b14610335578063b1b1b2091461036057600080fd5b80637dea7cc3146102f45780638129fc1c1461030b57600080fd5b80633f827a5a1161012d5780636425666b116101075780636425666b146102715780636e296e45146102ca578063715018a6146102df57600080fd5b80633f827a5a1461020357806354fd4d501461022b5780635c975abb1461024d57600080fd5b80632828d7e81161015e5780632828d7e8146101c35780633dbb202b146101d95780633f4ba83a146101ee57600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f6103e881565b3480156101cf57600080fd5b5061018f6103f881565b6101ec6101e7366004611de8565b6104ac565b005b3480156101fa57600080fd5b506101ec610710565b34801561020f57600080fd5b50610218600181565b60405161ffff90911681526020016101a4565b34801561023757600080fd5b50610240610722565b6040516101a49190611ec9565b34801561025957600080fd5b5060655460ff165b60405190151581526020016101a4565b34801561027d57600080fd5b506102a57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b3480156102d657600080fd5b506102a56107c5565b3480156102eb57600080fd5b506101ec6108b1565b34801561030057600080fd5b5061018f62030d4081565b34801561031757600080fd5b506101ec6108c3565b34801561032c57600080fd5b506101ec610ac0565b34801561034157600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166102a5565b34801561036c57600080fd5b5061026161037b366004611ee3565b60cb6020526000908152604090205460ff1681565b34801561039c57600080fd5b5061018f6103ab366004611efc565b610ad0565b6101ec6103be366004611f50565b610b1c565b3480156103cf57600080fd5b506102a57f000000000000000000000000000000000000000000000000000000000000000081565b34801561040357600080fd5b5061044e60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b34801561046857600080fd5b506101ec610477366004611fd6565b6111ad565b34801561048857600080fd5b50610261610497366004611ee3565b60ce6020526000908152604090205460ff1681565b6105e57f00000000000000000000000000000000000000000000000000000000000000006104db858585610ad0565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061054760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c604051602401610563979695949392919061203c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261127d565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561066a60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b8660405161067c95949392919061209b565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b610718611332565b6107206113b3565b565b606061074d7f0000000000000000000000000000000000000000000000000000000000000000611430565b6107767f0000000000000000000000000000000000000000000000000000000000000000611430565b61079f7f0000000000000000000000000000000000000000000000000000000000000000611430565b6040516020016107b1939291906120e9565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610894576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6108b9611332565b6107206000611565565b6000547501000000000000000000000000000000000000000000900460ff161580801561090e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109405750303b158015610940575060005474010000000000000000000000000000000000000000900460ff166001145b6109cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161088b565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610a5257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610a5a6115dc565b8015610abd57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610ac8611332565b6107206116d3565b600062030d40610ae160108561218e565b6103e8610af66103f863ffffffff871661218e565b610b0091906121ed565b610b0a9190612214565b610b149190612214565b949350505050565b600260975403610b88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161088b565b6002609755610b9561172e565b60f087901c60018114610c50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605560248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2031206d657373616765732061726520737570706f72746564206166746560648201527f722074686520426564726f636b20757067726164650000000000000000000000608482015260a40161088b565b6000610c96898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061179b92505050565b9050610ca06117be565b15610cb957853414610cb457610cb4612240565b610e0b565b3415610d6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161088b565b600081815260ce602052604090205460ff16610e0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161088b565b610e14876118e2565b15610ec7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161088b565b600081815260cb602052604090205460ff1615610f66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161088b565b610f7261afc88661226f565b5a1015611001576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a20696e737566666963696560448201527f6e742067617320746f2072656c6179206d657373616765000000000000000000606482015260840161088b565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061109d8861105561138861afc8612287565b5a6110609190612287565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061195992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560010361113857600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2611197565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a25b505060016097555050505050505050565b905090565b6111b5611332565b73ffffffffffffffffffffffffffffffffffffffff8116611258576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161088b565b610abd81611565565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c429084906112fa90889083908990600090899060040161229e565b6000604051808303818588803b15801561131357600080fd5b505af1158015611327573d6000803e3d6000fd5b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161088b565b6113bb611973565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60608160000361147357505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561149d5780611487816122f6565b91506114969050600a8361232e565b9150611477565b60008167ffffffffffffffff8111156114b8576114b8612342565b6040519080825280601f01601f1916602001820160405280156114e2576020820181803683370190505b5090505b8415610b14576114f7600183612287565b9150611504600a86612371565b61150f90603061226f565b60f81b81838151811061152457611524612385565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061155e600a8661232e565b94506114e6565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000547501000000000000000000000000000000000000000000900460ff16611687576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556116bb6119df565b6116c3611a8a565b6116cb611b3e565b610720611c13565b6116db61172e565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114063390565b60655460ff1615610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161088b565b60006117ab878787878787611cc5565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156111a857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c691906123b4565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff821630148061195357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080600080845160208601878a8af19695505050505050565b60655460ff16610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161088b565b6000547501000000000000000000000000000000000000000000900460ff16610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b6000547501000000000000000000000000000000000000000000900460ff16611b35576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b61072033611565565b6000547501000000000000000000000000000000000000000000900460ff16611be9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000547501000000000000000000000000000000000000000000900460ff16611cbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b6001609755565b6060868686868686604051602401611ce2969594939291906123d1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610abd57600080fd5b60008083601f840112611d9857600080fd5b50813567ffffffffffffffff811115611db057600080fd5b602083019150836020828501011115611dc857600080fd5b9250929050565b803563ffffffff81168114611de357600080fd5b919050565b60008060008060608587031215611dfe57600080fd5b8435611e0981611d64565b9350602085013567ffffffffffffffff811115611e2557600080fd5b611e3187828801611d86565b9094509250611e44905060408601611dcf565b905092959194509250565b60005b83811015611e6a578181015183820152602001611e52565b83811115611e79576000848401525b50505050565b60008151808452611e97816020860160208601611e4f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611edc6020830184611e7f565b9392505050565b600060208284031215611ef557600080fd5b5035919050565b600080600060408486031215611f1157600080fd5b833567ffffffffffffffff811115611f2857600080fd5b611f3486828701611d86565b9094509250611f47905060208501611dcf565b90509250925092565b600080600080600080600060c0888a031215611f6b57600080fd5b873596506020880135611f7d81611d64565b95506040880135611f8d81611d64565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611fb757600080fd5b611fc38a828b01611d86565b989b979a50959850939692959293505050565b600060208284031215611fe857600080fd5b8135611edc81611d64565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a083015261208e60c083018486611ff3565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff861681526080602082015260006120cb608083018688611ff3565b905083604083015263ffffffff831660608301529695505050505050565b600084516120fb818460208901611e4f565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612137816001850160208a01611e4f565b60019201918201528351612152816002840160208801611e4f565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff808316818516818304811182151516156121b5576121b561215f565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680612208576122086121be565b92169190910492915050565b600067ffffffffffffffff8083168185168083038211156122375761223761215f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082198211156122825761228261215f565b500190565b6000828210156122995761229961215f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a0608082015260006122eb60a0830184611e7f565b979650505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123275761232761215f565b5060010190565b60008261233d5761233d6121be565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082612380576123806121be565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123c657600080fd5b8151611edc81611d64565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261241c60c0830184611e7f565b9897505050505050505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", } // L1CrossDomainMessengerABI is the input ABI used to generate the binding from. @@ -234,16 +234,16 @@ func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) MESSAGEVERSI // MINGASCALLDATAOVERHEAD is a free data retrieval call binding the contract method 0x028f85f7. // -// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASCALLDATAOVERHEAD(opts *bind.CallOpts) (uint32, error) { +// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASCALLDATAOVERHEAD(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L1CrossDomainMessenger.contract.Call(opts, &out, "MIN_GAS_CALLDATA_OVERHEAD") if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -251,30 +251,30 @@ func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASCALLDATAOVERH // MINGASCALLDATAOVERHEAD is a free data retrieval call binding the contract method 0x028f85f7. // -// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) MINGASCALLDATAOVERHEAD() (uint32, error) { +// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) MINGASCALLDATAOVERHEAD() (uint64, error) { return _L1CrossDomainMessenger.Contract.MINGASCALLDATAOVERHEAD(&_L1CrossDomainMessenger.CallOpts) } // MINGASCALLDATAOVERHEAD is a free data retrieval call binding the contract method 0x028f85f7. // -// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) MINGASCALLDATAOVERHEAD() (uint32, error) { +// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) MINGASCALLDATAOVERHEAD() (uint64, error) { return _L1CrossDomainMessenger.Contract.MINGASCALLDATAOVERHEAD(&_L1CrossDomainMessenger.CallOpts) } // MINGASCONSTANTOVERHEAD is a free data retrieval call binding the contract method 0x7dea7cc3. // -// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASCONSTANTOVERHEAD(opts *bind.CallOpts) (uint32, error) { +// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASCONSTANTOVERHEAD(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L1CrossDomainMessenger.contract.Call(opts, &out, "MIN_GAS_CONSTANT_OVERHEAD") if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -282,30 +282,30 @@ func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASCONSTANTOVERH // MINGASCONSTANTOVERHEAD is a free data retrieval call binding the contract method 0x7dea7cc3. // -// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) MINGASCONSTANTOVERHEAD() (uint32, error) { +// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) MINGASCONSTANTOVERHEAD() (uint64, error) { return _L1CrossDomainMessenger.Contract.MINGASCONSTANTOVERHEAD(&_L1CrossDomainMessenger.CallOpts) } // MINGASCONSTANTOVERHEAD is a free data retrieval call binding the contract method 0x7dea7cc3. // -// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) MINGASCONSTANTOVERHEAD() (uint32, error) { +// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) MINGASCONSTANTOVERHEAD() (uint64, error) { return _L1CrossDomainMessenger.Contract.MINGASCONSTANTOVERHEAD(&_L1CrossDomainMessenger.CallOpts) } // MINGASDYNAMICOVERHEADDENOMINATOR is a free data retrieval call binding the contract method 0x0c568498. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASDYNAMICOVERHEADDENOMINATOR(opts *bind.CallOpts) (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASDYNAMICOVERHEADDENOMINATOR(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L1CrossDomainMessenger.contract.Call(opts, &out, "MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR") if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -313,30 +313,30 @@ func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASDYNAMICOVERHE // MINGASDYNAMICOVERHEADDENOMINATOR is a free data retrieval call binding the contract method 0x0c568498. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) MINGASDYNAMICOVERHEADDENOMINATOR() (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) MINGASDYNAMICOVERHEADDENOMINATOR() (uint64, error) { return _L1CrossDomainMessenger.Contract.MINGASDYNAMICOVERHEADDENOMINATOR(&_L1CrossDomainMessenger.CallOpts) } // MINGASDYNAMICOVERHEADDENOMINATOR is a free data retrieval call binding the contract method 0x0c568498. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) MINGASDYNAMICOVERHEADDENOMINATOR() (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) MINGASDYNAMICOVERHEADDENOMINATOR() (uint64, error) { return _L1CrossDomainMessenger.Contract.MINGASDYNAMICOVERHEADDENOMINATOR(&_L1CrossDomainMessenger.CallOpts) } // MINGASDYNAMICOVERHEADNUMERATOR is a free data retrieval call binding the contract method 0x2828d7e8. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASDYNAMICOVERHEADNUMERATOR(opts *bind.CallOpts) (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASDYNAMICOVERHEADNUMERATOR(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L1CrossDomainMessenger.contract.Call(opts, &out, "MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR") if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -344,30 +344,30 @@ func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) MINGASDYNAMICOVERHE // MINGASDYNAMICOVERHEADNUMERATOR is a free data retrieval call binding the contract method 0x2828d7e8. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) MINGASDYNAMICOVERHEADNUMERATOR() (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) MINGASDYNAMICOVERHEADNUMERATOR() (uint64, error) { return _L1CrossDomainMessenger.Contract.MINGASDYNAMICOVERHEADNUMERATOR(&_L1CrossDomainMessenger.CallOpts) } // MINGASDYNAMICOVERHEADNUMERATOR is a free data retrieval call binding the contract method 0x2828d7e8. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) MINGASDYNAMICOVERHEADNUMERATOR() (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) MINGASDYNAMICOVERHEADNUMERATOR() (uint64, error) { return _L1CrossDomainMessenger.Contract.MINGASDYNAMICOVERHEADNUMERATOR(&_L1CrossDomainMessenger.CallOpts) } // BaseGas is a free data retrieval call binding the contract method 0xb28ade25. // -// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) BaseGas(opts *bind.CallOpts, _message []byte, _minGasLimit uint32) (uint32, error) { +// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) BaseGas(opts *bind.CallOpts, _message []byte, _minGasLimit uint32) (uint64, error) { var out []interface{} err := _L1CrossDomainMessenger.contract.Call(opts, &out, "baseGas", _message, _minGasLimit) if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -375,15 +375,15 @@ func (_L1CrossDomainMessenger *L1CrossDomainMessengerCaller) BaseGas(opts *bind. // BaseGas is a free data retrieval call binding the contract method 0xb28ade25. // -// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) BaseGas(_message []byte, _minGasLimit uint32) (uint32, error) { +// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerSession) BaseGas(_message []byte, _minGasLimit uint32) (uint64, error) { return _L1CrossDomainMessenger.Contract.BaseGas(&_L1CrossDomainMessenger.CallOpts, _message, _minGasLimit) } // BaseGas is a free data retrieval call binding the contract method 0xb28ade25. // -// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint32) -func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) BaseGas(_message []byte, _minGasLimit uint32) (uint32, error) { +// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint64) +func (_L1CrossDomainMessenger *L1CrossDomainMessengerCallerSession) BaseGas(_message []byte, _minGasLimit uint32) (uint64, error) { return _L1CrossDomainMessenger.Contract.BaseGas(&_L1CrossDomainMessenger.CallOpts, _message, _minGasLimit) } diff --git a/op-bindings/bindings/l1crossdomainmessenger_more.go b/op-bindings/bindings/l1crossdomainmessenger_more.go index ac6b12ba4d743..a3970f530b242 100644 --- a/op-bindings/bindings/l1crossdomainmessenger_more.go +++ b/op-bindings/bindings/l1crossdomainmessenger_more.go @@ -9,11 +9,11 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const L1CrossDomainMessengerStorageLayoutJSON = "{\"storage\":[{\"astId\":24726,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":27112,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_initialized\",\"offset\":20,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":27115,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_initializing\",\"offset\":21,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":27726,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":26984,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":27104,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":27277,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_paused\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_bool\"},{\"astId\":27382,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":27397,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_status\",\"offset\":0,\"slot\":\"151\",\"type\":\"t_uint256\"},{\"astId\":27441,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"152\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":24778,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_201_0_32\",\"offset\":0,\"slot\":\"201\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24783,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_202_0_32\",\"offset\":0,\"slot\":\"202\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24788,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"successfulMessages\",\"offset\":0,\"slot\":\"203\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24791,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"xDomainMsgSender\",\"offset\":0,\"slot\":\"204\",\"type\":\"t_address\"},{\"astId\":24794,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"msgNonce\",\"offset\":0,\"slot\":\"205\",\"type\":\"t_uint240\"},{\"astId\":24799,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"receivedMessages\",\"offset\":0,\"slot\":\"206\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24804,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"207\",\"type\":\"t_array(t_uint256)42_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)42_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[42]\",\"numberOfBytes\":\"1344\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"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\"}}}" +const L1CrossDomainMessengerStorageLayoutJSON = "{\"storage\":[{\"astId\":24811,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":27200,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_initialized\",\"offset\":20,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":27203,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_initializing\",\"offset\":21,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":27814,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":27072,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":27192,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":27365,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_paused\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_bool\"},{\"astId\":27470,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":27485,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_status\",\"offset\":0,\"slot\":\"151\",\"type\":\"t_uint256\"},{\"astId\":27529,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"152\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":24863,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_201_0_32\",\"offset\":0,\"slot\":\"201\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24868,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_202_0_32\",\"offset\":0,\"slot\":\"202\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24873,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"successfulMessages\",\"offset\":0,\"slot\":\"203\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24876,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"xDomainMsgSender\",\"offset\":0,\"slot\":\"204\",\"type\":\"t_address\"},{\"astId\":24879,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"msgNonce\",\"offset\":0,\"slot\":\"205\",\"type\":\"t_uint240\"},{\"astId\":24884,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"receivedMessages\",\"offset\":0,\"slot\":\"206\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24889,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"207\",\"type\":\"t_array(t_uint256)42_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)42_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[42]\",\"numberOfBytes\":\"1344\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"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\"}}}" var L1CrossDomainMessengerStorageLayout = new(solc.StorageLayout) -var L1CrossDomainMessengerDeployedBin = "0x6080604052600436106101755760003560e01c80637dea7cc3116100cb578063b28ade251161007f578063ecc7042811610059578063ecc70428146103f3578063f2fde38b14610458578063f69f81511461047857600080fd5b8063b28ade251461038c578063d764ad0b146103ac578063db505d80146103bf57600080fd5b80638456cb59116100b05780638456cb591461031c5780638da5cb5b14610331578063b1b1b2091461035c57600080fd5b80637dea7cc3146102f05780638129fc1c1461030757600080fd5b80633f827a5a1161012d5780636425666b116101075780636425666b1461026d5780636e296e45146102c6578063715018a6146102db57600080fd5b80633f827a5a146101ff57806354fd4d50146102275780635c975abb1461024957600080fd5b80632828d7e81161015e5780632828d7e8146101bf5780633dbb202b146101d55780633f4ba83a146101ea57600080fd5b8063028f85f71461017a5780630c568498146101a9575b600080fd5b34801561018657600080fd5b5061018f601081565b60405163ffffffff90911681526020015b60405180910390f35b3480156101b557600080fd5b5061018f6103e881565b3480156101cb57600080fd5b5061018f6103f881565b6101e86101e3366004611de4565b6104a8565b005b3480156101f657600080fd5b506101e8610712565b34801561020b57600080fd5b50610214600181565b60405161ffff90911681526020016101a0565b34801561023357600080fd5b5061023c610724565b6040516101a09190611ec5565b34801561025557600080fd5b5060655460ff165b60405190151581526020016101a0565b34801561027957600080fd5b506102a17f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a0565b3480156102d257600080fd5b506102a16107c7565b3480156102e757600080fd5b506101e86108b3565b3480156102fc57600080fd5b5061018f62030d4081565b34801561031357600080fd5b506101e86108c5565b34801561032857600080fd5b506101e8610ac2565b34801561033d57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166102a1565b34801561036857600080fd5b5061025d610377366004611edf565b60cb6020526000908152604090205460ff1681565b34801561039857600080fd5b5061018f6103a7366004611ef8565b610ad2565b6101e86103ba366004611f4c565b610b18565b3480156103cb57600080fd5b506102a17f000000000000000000000000000000000000000000000000000000000000000081565b3480156103ff57600080fd5b5061044a60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a0565b34801561046457600080fd5b506101e8610473366004611fd2565b6111a9565b34801561048457600080fd5b5061025d610493366004611edf565b60ce6020526000908152604090205460ff1681565b6105e77f00000000000000000000000000000000000000000000000000000000000000006104d7858585610ad2565b63ffffffff16347fd764ad0b0000000000000000000000000000000000000000000000000000000061054960cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105659796959493929190612038565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611279565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561066c60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b8660405161067e959493929190612097565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b61071a61132e565b6107226113af565b565b606061074f7f000000000000000000000000000000000000000000000000000000000000000061142c565b6107787f000000000000000000000000000000000000000000000000000000000000000061142c565b6107a17f000000000000000000000000000000000000000000000000000000000000000061142c565b6040516020016107b3939291906120e5565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6108bb61132e565b6107226000611561565b6000547501000000000000000000000000000000000000000000900460ff1615808015610910575060005460017401000000000000000000000000000000000000000090910460ff16105b806109425750303b158015610942575060005474010000000000000000000000000000000000000000900460ff166001145b6109ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161088d565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610a5457600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610a5c6115d8565b8015610abf57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610aca61132e565b6107226116cf565b600062030d40610ae360108561218a565b6103e8610af26103f88661218a565b610afc91906121e5565b610b069190612208565b610b109190612208565b949350505050565b600260975403610b84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161088d565b6002609755610b9161172a565b60f087901c60018114610c4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605560248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2031206d657373616765732061726520737570706f72746564206166746560648201527f722074686520426564726f636b20757067726164650000000000000000000000608482015260a40161088d565b6000610c92898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061179792505050565b9050610c9c6117ba565b15610cb557853414610cb057610cb0612230565b610e07565b3415610d69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161088d565b600081815260ce602052604090205460ff16610e07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161088d565b610e10876118de565b15610ec3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161088d565b600081815260cb602052604090205460ff1615610f62576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161088d565b610f6e61afc88661225f565b5a1015610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a20696e737566666963696560448201527f6e742067617320746f2072656c6179206d657373616765000000000000000000606482015260840161088d565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006110998861105161138861afc8612277565b5a61105c9190612277565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061195592505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560010361113457600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2611193565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a25b505060016097555050505050505050565b905090565b6111b161132e565b73ffffffffffffffffffffffffffffffffffffffff8116611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161088d565b610abf81611561565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c429084906112f690889083908990600090899060040161228e565b6000604051808303818588803b15801561130f57600080fd5b505af1158015611323573d6000803e3d6000fd5b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161088d565b6113b761196f565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60608160000361146f57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156114995780611483816122e6565b91506114929050600a8361231e565b9150611473565b60008167ffffffffffffffff8111156114b4576114b4612332565b6040519080825280601f01601f1916602001820160405280156114de576020820181803683370190505b5090505b8415610b10576114f3600183612277565b9150611500600a86612361565b61150b90603061225f565b60f81b81838151811061152057611520612375565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061155a600a8661231e565b94506114e2565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000547501000000000000000000000000000000000000000000900460ff16611683576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556116b76119db565b6116bf611a86565b6116c7611b3a565b610722611c0f565b6116d761172a565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114023390565b60655460ff1615610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161088d565b60006117a7878787878787611cc1565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156111a457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa15801561189e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c291906123a4565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff821630148061194f57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080600080845160208601878a8af19695505050505050565b60655460ff16610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161088d565b6000547501000000000000000000000000000000000000000000900460ff16610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b6000547501000000000000000000000000000000000000000000900460ff16611b31576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b61072233611561565b6000547501000000000000000000000000000000000000000000900460ff16611be5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000547501000000000000000000000000000000000000000000900460ff16611cba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088d565b6001609755565b6060868686868686604051602401611cde969594939291906123c1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610abf57600080fd5b60008083601f840112611d9457600080fd5b50813567ffffffffffffffff811115611dac57600080fd5b602083019150836020828501011115611dc457600080fd5b9250929050565b803563ffffffff81168114611ddf57600080fd5b919050565b60008060008060608587031215611dfa57600080fd5b8435611e0581611d60565b9350602085013567ffffffffffffffff811115611e2157600080fd5b611e2d87828801611d82565b9094509250611e40905060408601611dcb565b905092959194509250565b60005b83811015611e66578181015183820152602001611e4e565b83811115611e75576000848401525b50505050565b60008151808452611e93816020860160208601611e4b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ed86020830184611e7b565b9392505050565b600060208284031215611ef157600080fd5b5035919050565b600080600060408486031215611f0d57600080fd5b833567ffffffffffffffff811115611f2457600080fd5b611f3086828701611d82565b9094509250611f43905060208501611dcb565b90509250925092565b600080600080600080600060c0888a031215611f6757600080fd5b873596506020880135611f7981611d60565b95506040880135611f8981611d60565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611fb357600080fd5b611fbf8a828b01611d82565b989b979a50959850939692959293505050565b600060208284031215611fe457600080fd5b8135611ed881611d60565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a083015261208a60c083018486611fef565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff861681526080602082015260006120c7608083018688611fef565b905083604083015263ffffffff831660608301529695505050505050565b600084516120f7818460208901611e4b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612133816001850160208a01611e4b565b6001920191820152835161214e816002840160208801611e4b565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818516818304811182151516156121ad576121ad61215b565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600063ffffffff808416806121fc576121fc6121b6565b92169190910492915050565b600063ffffffff8083168185168083038211156122275761222761215b565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082198211156122725761227261215b565b500190565b6000828210156122895761228961215b565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a0608082015260006122db60a0830184611e7b565b979650505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123175761231761215b565b5060010190565b60008261232d5761232d6121b6565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082612370576123706121b6565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123b657600080fd5b8151611ed881611d60565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261240c60c0830184611e7b565b9897505050505050505056fea164736f6c634300080f000a" +var L1CrossDomainMessengerDeployedBin = "0x6080604052600436106101755760003560e01c80637dea7cc3116100cb578063b28ade251161007f578063ecc7042811610059578063ecc70428146103f7578063f2fde38b1461045c578063f69f81511461047c57600080fd5b8063b28ade2514610390578063d764ad0b146103b0578063db505d80146103c357600080fd5b80638456cb59116100b05780638456cb59146103205780638da5cb5b14610335578063b1b1b2091461036057600080fd5b80637dea7cc3146102f45780638129fc1c1461030b57600080fd5b80633f827a5a1161012d5780636425666b116101075780636425666b146102715780636e296e45146102ca578063715018a6146102df57600080fd5b80633f827a5a1461020357806354fd4d501461022b5780635c975abb1461024d57600080fd5b80632828d7e81161015e5780632828d7e8146101c35780633dbb202b146101d95780633f4ba83a146101ee57600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f6103e881565b3480156101cf57600080fd5b5061018f6103f881565b6101ec6101e7366004611de8565b6104ac565b005b3480156101fa57600080fd5b506101ec610710565b34801561020f57600080fd5b50610218600181565b60405161ffff90911681526020016101a4565b34801561023757600080fd5b50610240610722565b6040516101a49190611ec9565b34801561025957600080fd5b5060655460ff165b60405190151581526020016101a4565b34801561027d57600080fd5b506102a57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b3480156102d657600080fd5b506102a56107c5565b3480156102eb57600080fd5b506101ec6108b1565b34801561030057600080fd5b5061018f62030d4081565b34801561031757600080fd5b506101ec6108c3565b34801561032c57600080fd5b506101ec610ac0565b34801561034157600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166102a5565b34801561036c57600080fd5b5061026161037b366004611ee3565b60cb6020526000908152604090205460ff1681565b34801561039c57600080fd5b5061018f6103ab366004611efc565b610ad0565b6101ec6103be366004611f50565b610b1c565b3480156103cf57600080fd5b506102a57f000000000000000000000000000000000000000000000000000000000000000081565b34801561040357600080fd5b5061044e60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b34801561046857600080fd5b506101ec610477366004611fd6565b6111ad565b34801561048857600080fd5b50610261610497366004611ee3565b60ce6020526000908152604090205460ff1681565b6105e57f00000000000000000000000000000000000000000000000000000000000000006104db858585610ad0565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061054760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c604051602401610563979695949392919061203c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261127d565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561066a60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b8660405161067c95949392919061209b565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b610718611332565b6107206113b3565b565b606061074d7f0000000000000000000000000000000000000000000000000000000000000000611430565b6107767f0000000000000000000000000000000000000000000000000000000000000000611430565b61079f7f0000000000000000000000000000000000000000000000000000000000000000611430565b6040516020016107b1939291906120e9565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610894576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6108b9611332565b6107206000611565565b6000547501000000000000000000000000000000000000000000900460ff161580801561090e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109405750303b158015610940575060005474010000000000000000000000000000000000000000900460ff166001145b6109cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161088b565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610a5257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610a5a6115dc565b8015610abd57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610ac8611332565b6107206116d3565b600062030d40610ae160108561218e565b6103e8610af66103f863ffffffff871661218e565b610b0091906121ed565b610b0a9190612214565b610b149190612214565b949350505050565b600260975403610b88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161088b565b6002609755610b9561172e565b60f087901c60018114610c50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605560248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2031206d657373616765732061726520737570706f72746564206166746560648201527f722074686520426564726f636b20757067726164650000000000000000000000608482015260a40161088b565b6000610c96898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061179b92505050565b9050610ca06117be565b15610cb957853414610cb457610cb4612240565b610e0b565b3415610d6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161088b565b600081815260ce602052604090205460ff16610e0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161088b565b610e14876118e2565b15610ec7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161088b565b600081815260cb602052604090205460ff1615610f66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161088b565b610f7261afc88661226f565b5a1015611001576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a20696e737566666963696560448201527f6e742067617320746f2072656c6179206d657373616765000000000000000000606482015260840161088b565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061109d8861105561138861afc8612287565b5a6110609190612287565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061195992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560010361113857600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2611197565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a25b505060016097555050505050505050565b905090565b6111b5611332565b73ffffffffffffffffffffffffffffffffffffffff8116611258576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161088b565b610abd81611565565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c429084906112fa90889083908990600090899060040161229e565b6000604051808303818588803b15801561131357600080fd5b505af1158015611327573d6000803e3d6000fd5b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161088b565b6113bb611973565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60608160000361147357505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561149d5780611487816122f6565b91506114969050600a8361232e565b9150611477565b60008167ffffffffffffffff8111156114b8576114b8612342565b6040519080825280601f01601f1916602001820160405280156114e2576020820181803683370190505b5090505b8415610b14576114f7600183612287565b9150611504600a86612371565b61150f90603061226f565b60f81b81838151811061152457611524612385565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061155e600a8661232e565b94506114e6565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000547501000000000000000000000000000000000000000000900460ff16611687576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556116bb6119df565b6116c3611a8a565b6116cb611b3e565b610720611c13565b6116db61172e565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114063390565b60655460ff1615610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161088b565b60006117ab878787878787611cc5565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156111a857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c691906123b4565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff821630148061195357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080600080845160208601878a8af19695505050505050565b60655460ff16610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161088b565b6000547501000000000000000000000000000000000000000000900460ff16610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b6000547501000000000000000000000000000000000000000000900460ff16611b35576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b61072033611565565b6000547501000000000000000000000000000000000000000000900460ff16611be9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000547501000000000000000000000000000000000000000000900460ff16611cbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088b565b6001609755565b6060868686868686604051602401611ce2969594939291906123d1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610abd57600080fd5b60008083601f840112611d9857600080fd5b50813567ffffffffffffffff811115611db057600080fd5b602083019150836020828501011115611dc857600080fd5b9250929050565b803563ffffffff81168114611de357600080fd5b919050565b60008060008060608587031215611dfe57600080fd5b8435611e0981611d64565b9350602085013567ffffffffffffffff811115611e2557600080fd5b611e3187828801611d86565b9094509250611e44905060408601611dcf565b905092959194509250565b60005b83811015611e6a578181015183820152602001611e52565b83811115611e79576000848401525b50505050565b60008151808452611e97816020860160208601611e4f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611edc6020830184611e7f565b9392505050565b600060208284031215611ef557600080fd5b5035919050565b600080600060408486031215611f1157600080fd5b833567ffffffffffffffff811115611f2857600080fd5b611f3486828701611d86565b9094509250611f47905060208501611dcf565b90509250925092565b600080600080600080600060c0888a031215611f6b57600080fd5b873596506020880135611f7d81611d64565b95506040880135611f8d81611d64565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611fb757600080fd5b611fc38a828b01611d86565b989b979a50959850939692959293505050565b600060208284031215611fe857600080fd5b8135611edc81611d64565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a083015261208e60c083018486611ff3565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff861681526080602082015260006120cb608083018688611ff3565b905083604083015263ffffffff831660608301529695505050505050565b600084516120fb818460208901611e4f565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612137816001850160208a01611e4f565b60019201918201528351612152816002840160208801611e4f565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff808316818516818304811182151516156121b5576121b561215f565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680612208576122086121be565b92169190910492915050565b600067ffffffffffffffff8083168185168083038211156122375761223761215f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082198211156122825761228261215f565b500190565b6000828210156122995761229961215f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a0608082015260006122eb60a0830184611e7f565b979650505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123275761232761215f565b5060010190565b60008261233d5761233d6121be565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082612380576123806121be565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156123c657600080fd5b8151611edc81611d64565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261241c60c0830184611e7f565b9897505050505050505056fea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(L1CrossDomainMessengerStorageLayoutJSON), L1CrossDomainMessengerStorageLayout); err != nil { diff --git a/op-bindings/bindings/l2crossdomainmessenger.go b/op-bindings/bindings/l2crossdomainmessenger.go index c2a9dc9e0b245..cce8c16fddb14 100644 --- a/op-bindings/bindings/l2crossdomainmessenger.go +++ b/op-bindings/bindings/l2crossdomainmessenger.go @@ -30,8 +30,8 @@ var ( // L2CrossDomainMessengerMetaData contains all meta data concerning the L2CrossDomainMessenger contract. var L2CrossDomainMessengerMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1CrossDomainMessenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"FailedRelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"RelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"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\"}],\"name\":\"SentMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SentMessageExtension1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1CrossDomainMessenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherMessenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"receivedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"relayMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"sendMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b50604051620027b8380380620027b8833981016040819052620000359162000442565b6001600160a01b038116608052600060a081905260c052600160e0526200005b62000062565b5062000474565b600054600160a81b900460ff16158080156200008b57506000546001600160a01b90910460ff16105b80620000c25750620000a830620001af60201b620012ad1760201c565b158015620000c25750600054600160a01b900460ff166001145b6200012b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000159576000805460ff60a81b1916600160a81b1790555b62000163620001be565b8015620001ac576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054600160a81b900460ff166200021c5760405162461bcd60e51b815260206004820152602b60248201526000805160206200279883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b60cc80546001600160a01b03191661dead1790556200023a6200025a565b62000244620002b8565b6200024e62000321565b620002586200038b565b565b600054600160a81b900460ff16620002585760405162461bcd60e51b815260206004820152602b60248201526000805160206200279883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b600054600160a81b900460ff16620003165760405162461bcd60e51b815260206004820152602b60248201526000805160206200279883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b6200025833620003f0565b600054600160a81b900460ff166200037f5760405162461bcd60e51b815260206004820152602b60248201526000805160206200279883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b6065805460ff19169055565b600054600160a81b900460ff16620003e95760405162461bcd60e51b815260206004820152602b60248201526000805160206200279883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b6001609755565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000602082840312156200045557600080fd5b81516001600160a01b03811681146200046d57600080fd5b9392505050565b60805160a05160c05160e0516122d5620004c3600039600061077c015260006107530152600061072a015260008181610337015281816103d0015281816104ac0152610ccf01526122d56000f3fe6080604052600436106101755760003560e01c80638129fc1c116100cb578063b28ade251161007f578063ecc7042811610059578063ecc70428146103f2578063f2fde38b14610457578063f69f81511461047757600080fd5b8063b28ade251461038b578063d764ad0b146103ab578063db505d80146103be57600080fd5b80638da5cb5b116100b05780638da5cb5b146102fd578063a711986914610328578063b1b1b2091461035b57600080fd5b80638129fc1c146102d35780638456cb59146102e857600080fd5b80633f827a5a1161012d5780636e296e45116101075780636e296e451461026d578063715018a6146102a75780637dea7cc3146102bc57600080fd5b80633f827a5a146101ff57806354fd4d50146102275780635c975abb1461024957600080fd5b80632828d7e81161015e5780632828d7e8146101bf5780633dbb202b146101d55780633f4ba83a146101ea57600080fd5b8063028f85f71461017a5780630c568498146101a9575b600080fd5b34801561018657600080fd5b5061018f601081565b60405163ffffffff90911681526020015b60405180910390f35b3480156101b557600080fd5b5061018f6103e881565b3480156101cb57600080fd5b5061018f6103f881565b6101e86101e3366004611cc9565b6104a7565b005b3480156101f657600080fd5b506101e8610711565b34801561020b57600080fd5b50610214600181565b60405161ffff90911681526020016101a0565b34801561023357600080fd5b5061023c610723565b6040516101a09190611da8565b34801561025557600080fd5b5060655460ff165b60405190151581526020016101a0565b34801561027957600080fd5b506102826107c6565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a0565b3480156102b357600080fd5b506101e86108b2565b3480156102c857600080fd5b5061018f62030d4081565b3480156102df57600080fd5b506101e86108c4565b3480156102f457600080fd5b506101e8610ac1565b34801561030957600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610282565b34801561033457600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610282565b34801561036757600080fd5b5061025d610376366004611dc2565b60cb6020526000908152604090205460ff1681565b34801561039757600080fd5b5061018f6103a6366004611ddb565b610ad1565b6101e86103b9366004611e2f565b610b17565b3480156103ca57600080fd5b506102827f000000000000000000000000000000000000000000000000000000000000000081565b3480156103fe57600080fd5b5061044960cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a0565b34801561046357600080fd5b506101e8610472366004611eb1565b6111f9565b34801561048357600080fd5b5061025d610492366004611dc2565b60ce6020526000908152604090205460ff1681565b6105e67f00000000000000000000000000000000000000000000000000000000000000006104d6858585610ad1565b63ffffffff16347fd764ad0b0000000000000000000000000000000000000000000000000000000061054860cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105649796959493929190611f15565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526112c9565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561066b60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b8660405161067d959493929190611f74565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b610719611357565b6107216113d8565b565b606061074e7f0000000000000000000000000000000000000000000000000000000000000000611455565b6107777f0000000000000000000000000000000000000000000000000000000000000000611455565b6107a07f0000000000000000000000000000000000000000000000000000000000000000611455565b6040516020016107b293929190611fc2565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610895576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6108ba611357565b610721600061158a565b6000547501000000000000000000000000000000000000000000900460ff161580801561090f575060005460017401000000000000000000000000000000000000000090910460ff16105b806109415750303b158015610941575060005474010000000000000000000000000000000000000000900460ff166001145b6109cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161088c565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610a5357600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610a5b611601565b8015610abe57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610ac9611357565b6107216116f8565b600062030d40610ae2601085612067565b6103e8610af16103f886612067565b610afb91906120c2565b610b0591906120e5565b610b0f91906120e5565b949350505050565b600260975403610b83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161088c565b6002609755610b90611753565b60f087901c60018114610c4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605560248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2031206d657373616765732061726520737570706f72746564206166746560648201527f722074686520426564726f636b20757067726164650000000000000000000000608482015260a40161088c565b6000610c91898989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117c092505050565b905073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef330181167f000000000000000000000000000000000000000000000000000000000000000090911603610d0a57853414610d0557610d0561210d565b610e5c565b3415610dbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161088c565b600081815260ce602052604090205460ff16610e5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161088c565b610e65876117e3565b15610f18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161088c565b600081815260cb602052604090205460ff1615610fb7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161088c565b610fc361afc88661213c565b5a1015611052576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a20696e737566666963696560448201527f6e742067617320746f2072656c6179206d657373616765000000000000000000606482015260840161088c565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006110ee886110a661138861afc8612154565b5a6110b19190612154565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061183892505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560010361118957600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26111e8565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a25b505060016097555050505050505050565b611201611357565b73ffffffffffffffffffffffffffffffffffffffff81166112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161088c565b610abe8161158a565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fc2b3e5ac0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000169063c2b3e5ac90849061131f9088908890879060040161216b565b6000604051808303818588803b15801561133857600080fd5b505af115801561134c573d6000803e3d6000fd5b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161088c565b6113e0611852565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60608160000361149857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156114c257806114ac816121b3565b91506114bb9050600a836121eb565b915061149c565b60008167ffffffffffffffff8111156114dd576114dd6121ff565b6040519080825280601f01601f191660200182016040528015611507576020820181803683370190505b5090505b8415610b0f5761151c600183612154565b9150611529600a8661222e565b61153490603061213c565b60f81b81838151811061154957611549612242565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611583600a866121eb565b945061150b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000547501000000000000000000000000000000000000000000900460ff166116ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556116e06118be565b6116e8611969565b6116f0611a1d565b610721611af2565b611700611753565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861142b3390565b60655460ff1615610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161088c565b60006117d0878787878787611ba4565b8051906020012090509695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611832575073ffffffffffffffffffffffffffffffffffffffff8216734200000000000000000000000000000000000016145b92915050565b600080600080845160208601878a8af19695505050505050565b60655460ff16610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161088c565b6000547501000000000000000000000000000000000000000000900460ff16610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b6000547501000000000000000000000000000000000000000000900460ff16611a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b6107213361158a565b6000547501000000000000000000000000000000000000000000900460ff16611ac8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000547501000000000000000000000000000000000000000000900460ff16611b9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b6001609755565b6060868686868686604051602401611bc196959493929190612271565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c6757600080fd5b919050565b60008083601f840112611c7e57600080fd5b50813567ffffffffffffffff811115611c9657600080fd5b602083019150836020828501011115611cae57600080fd5b9250929050565b803563ffffffff81168114611c6757600080fd5b60008060008060608587031215611cdf57600080fd5b611ce885611c43565b9350602085013567ffffffffffffffff811115611d0457600080fd5b611d1087828801611c6c565b9094509250611d23905060408601611cb5565b905092959194509250565b60005b83811015611d49578181015183820152602001611d31565b83811115611d58576000848401525b50505050565b60008151808452611d76816020860160208601611d2e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611dbb6020830184611d5e565b9392505050565b600060208284031215611dd457600080fd5b5035919050565b600080600060408486031215611df057600080fd5b833567ffffffffffffffff811115611e0757600080fd5b611e1386828701611c6c565b9094509250611e26905060208501611cb5565b90509250925092565b600080600080600080600060c0888a031215611e4a57600080fd5b87359650611e5a60208901611c43565b9550611e6860408901611c43565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611e9257600080fd5b611e9e8a828b01611c6c565b989b979a50959850939692959293505050565b600060208284031215611ec357600080fd5b611dbb82611c43565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611f6760c083018486611ecc565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611fa4608083018688611ecc565b905083604083015263ffffffff831660608301529695505050505050565b60008451611fd4818460208901611d2e565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612010816001850160208a01611d2e565b6001920191820152835161202b816002840160208801611d2e565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff8083168185168183048111821515161561208a5761208a612038565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600063ffffffff808416806120d9576120d9612093565b92169190910492915050565b600063ffffffff80831681851680830382111561210457612104612038565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000821982111561214f5761214f612038565b500190565b60008282101561216657612166612038565b500390565b73ffffffffffffffffffffffffffffffffffffffff8416815267ffffffffffffffff831660208201526060604082015260006121aa6060830184611d5e565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121e4576121e4612038565b5060010190565b6000826121fa576121fa612093565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008261223d5761223d612093565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526122bc60c0830184611d5e565b9897505050505050505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1CrossDomainMessenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"FailedRelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"RelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"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\"}],\"name\":\"SentMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SentMessageExtension1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1CrossDomainMessenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherMessenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"receivedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"relayMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"sendMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b50604051620027c8380380620027c8833981016040819052620000359162000442565b6001600160a01b038116608052600060a081905260c052600160e0526200005b62000062565b5062000474565b600054600160a81b900460ff16158080156200008b57506000546001600160a01b90910460ff16105b80620000c25750620000a830620001af60201b620012b11760201c565b158015620000c25750600054600160a01b900460ff166001145b6200012b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000159576000805460ff60a81b1916600160a81b1790555b62000163620001be565b8015620001ac576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054600160a81b900460ff166200021c5760405162461bcd60e51b815260206004820152602b6024820152600080516020620027a883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b60cc80546001600160a01b03191661dead1790556200023a6200025a565b62000244620002b8565b6200024e62000321565b620002586200038b565b565b600054600160a81b900460ff16620002585760405162461bcd60e51b815260206004820152602b6024820152600080516020620027a883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b600054600160a81b900460ff16620003165760405162461bcd60e51b815260206004820152602b6024820152600080516020620027a883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b6200025833620003f0565b600054600160a81b900460ff166200037f5760405162461bcd60e51b815260206004820152602b6024820152600080516020620027a883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b6065805460ff19169055565b600054600160a81b900460ff16620003e95760405162461bcd60e51b815260206004820152602b6024820152600080516020620027a883398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000122565b6001609755565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000602082840312156200045557600080fd5b81516001600160a01b03811681146200046d57600080fd5b9392505050565b60805160a05160c05160e0516122e5620004c3600039600061077a015260006107510152600061072801526000818161033b015281816103d4015281816104b00152610cd301526122e56000f3fe6080604052600436106101755760003560e01c80638129fc1c116100cb578063b28ade251161007f578063ecc7042811610059578063ecc70428146103f6578063f2fde38b1461045b578063f69f81511461047b57600080fd5b8063b28ade251461038f578063d764ad0b146103af578063db505d80146103c257600080fd5b80638da5cb5b116100b05780638da5cb5b14610301578063a71198691461032c578063b1b1b2091461035f57600080fd5b80638129fc1c146102d75780638456cb59146102ec57600080fd5b80633f827a5a1161012d5780636e296e45116101075780636e296e4514610271578063715018a6146102ab5780637dea7cc3146102c057600080fd5b80633f827a5a1461020357806354fd4d501461022b5780635c975abb1461024d57600080fd5b80632828d7e81161015e5780632828d7e8146101c35780633dbb202b146101d95780633f4ba83a146101ee57600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f6103e881565b3480156101cf57600080fd5b5061018f6103f881565b6101ec6101e7366004611ccd565b6104ab565b005b3480156101fa57600080fd5b506101ec61070f565b34801561020f57600080fd5b50610218600181565b60405161ffff90911681526020016101a4565b34801561023757600080fd5b50610240610721565b6040516101a49190611dac565b34801561025957600080fd5b5060655460ff165b60405190151581526020016101a4565b34801561027d57600080fd5b506102866107c4565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b3480156102b757600080fd5b506101ec6108b0565b3480156102cc57600080fd5b5061018f62030d4081565b3480156102e357600080fd5b506101ec6108c2565b3480156102f857600080fd5b506101ec610abf565b34801561030d57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610286565b34801561033857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610286565b34801561036b57600080fd5b5061026161037a366004611dc6565b60cb6020526000908152604090205460ff1681565b34801561039b57600080fd5b5061018f6103aa366004611ddf565b610acf565b6101ec6103bd366004611e33565b610b1b565b3480156103ce57600080fd5b506102867f000000000000000000000000000000000000000000000000000000000000000081565b34801561040257600080fd5b5061044d60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b34801561046757600080fd5b506101ec610476366004611eb5565b6111fd565b34801561048757600080fd5b50610261610496366004611dc6565b60ce6020526000908152604090205460ff1681565b6105e47f00000000000000000000000000000000000000000000000000000000000000006104da858585610acf565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061054660cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105629796959493929190611f19565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526112cd565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561066960cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b8660405161067b959493929190611f78565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b61071761135b565b61071f6113dc565b565b606061074c7f0000000000000000000000000000000000000000000000000000000000000000611459565b6107757f0000000000000000000000000000000000000000000000000000000000000000611459565b61079e7f0000000000000000000000000000000000000000000000000000000000000000611459565b6040516020016107b093929190611fc6565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6108b861135b565b61071f600061158e565b6000547501000000000000000000000000000000000000000000900460ff161580801561090d575060005460017401000000000000000000000000000000000000000090910460ff16105b8061093f5750303b15801561093f575060005474010000000000000000000000000000000000000000900460ff166001145b6109cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161088a565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610a5157600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610a59611605565b8015610abc57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610ac761135b565b61071f6116fc565b600062030d40610ae060108561206b565b6103e8610af56103f863ffffffff871661206b565b610aff91906120ca565b610b0991906120f1565b610b1391906120f1565b949350505050565b600260975403610b87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161088a565b6002609755610b94611757565b60f087901c60018114610c4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605560248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2031206d657373616765732061726520737570706f72746564206166746560648201527f722074686520426564726f636b20757067726164650000000000000000000000608482015260a40161088a565b6000610c95898989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117c492505050565b905073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef330181167f000000000000000000000000000000000000000000000000000000000000000090911603610d0e57853414610d0957610d0961211d565b610e60565b3415610dc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161088a565b600081815260ce602052604090205460ff16610e60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161088a565b610e69876117e7565b15610f1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161088a565b600081815260cb602052604090205460ff1615610fbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161088a565b610fc761afc88661214c565b5a1015611056576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a20696e737566666963696560448201527f6e742067617320746f2072656c6179206d657373616765000000000000000000606482015260840161088a565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006110f2886110aa61138861afc8612164565b5a6110b59190612164565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061183c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560010361118d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26111ec565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a25b505060016097555050505050505050565b61120561135b565b73ffffffffffffffffffffffffffffffffffffffff81166112a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161088a565b610abc8161158e565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fc2b3e5ac0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000169063c2b3e5ac9084906113239088908890879060040161217b565b6000604051808303818588803b15801561133c57600080fd5b505af1158015611350573d6000803e3d6000fd5b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff16331461071f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161088a565b6113e4611856565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60608160000361149c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156114c657806114b0816121c3565b91506114bf9050600a836121fb565b91506114a0565b60008167ffffffffffffffff8111156114e1576114e161220f565b6040519080825280601f01601f19166020018201604052801561150b576020820181803683370190505b5090505b8415610b1357611520600183612164565b915061152d600a8661223e565b61153890603061214c565b60f81b81838151811061154d5761154d612252565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611587600a866121fb565b945061150f565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000547501000000000000000000000000000000000000000000900460ff166116b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556116e46118c2565b6116ec61196d565b6116f4611a21565b61071f611af6565b611704611757565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861142f3390565b60655460ff161561071f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161088a565b60006117d4878787878787611ba8565b8051906020012090509695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611836575073ffffffffffffffffffffffffffffffffffffffff8216734200000000000000000000000000000000000016145b92915050565b600080600080845160208601878a8af19695505050505050565b60655460ff1661071f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161088a565b6000547501000000000000000000000000000000000000000000900460ff1661071f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b6000547501000000000000000000000000000000000000000000900460ff16611a18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b61071f3361158e565b6000547501000000000000000000000000000000000000000000900460ff16611acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000547501000000000000000000000000000000000000000000900460ff16611ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b6001609755565b6060868686868686604051602401611bc596959493929190612281565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c6b57600080fd5b919050565b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b803563ffffffff81168114611c6b57600080fd5b60008060008060608587031215611ce357600080fd5b611cec85611c47565b9350602085013567ffffffffffffffff811115611d0857600080fd5b611d1487828801611c70565b9094509250611d27905060408601611cb9565b905092959194509250565b60005b83811015611d4d578181015183820152602001611d35565b83811115611d5c576000848401525b50505050565b60008151808452611d7a816020860160208601611d32565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611dbf6020830184611d62565b9392505050565b600060208284031215611dd857600080fd5b5035919050565b600080600060408486031215611df457600080fd5b833567ffffffffffffffff811115611e0b57600080fd5b611e1786828701611c70565b9094509250611e2a905060208501611cb9565b90509250925092565b600080600080600080600060c0888a031215611e4e57600080fd5b87359650611e5e60208901611c47565b9550611e6c60408901611c47565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611e9657600080fd5b611ea28a828b01611c70565b989b979a50959850939692959293505050565b600060208284031215611ec757600080fd5b611dbf82611c47565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611f6b60c083018486611ed0565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611fa8608083018688611ed0565b905083604083015263ffffffff831660608301529695505050505050565b60008451611fd8818460208901611d32565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612014816001850160208a01611d32565b6001920191820152835161202f816002840160208801611d32565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff808316818516818304811182151516156120925761209261203c565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff808416806120e5576120e561209b565b92169190910492915050565b600067ffffffffffffffff8083168185168083038211156121145761211461203c565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000821982111561215f5761215f61203c565b500190565b6000828210156121765761217661203c565b500390565b73ffffffffffffffffffffffffffffffffffffffff8416815267ffffffffffffffff831660208201526060604082015260006121ba6060830184611d62565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121f4576121f461203c565b5060010190565b60008261220a5761220a61209b565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008261224d5761224d61209b565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526122cc60c0830184611d62565b9897505050505050505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", } // L2CrossDomainMessengerABI is the input ABI used to generate the binding from. @@ -234,16 +234,16 @@ func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) MESSAGEVERSI // MINGASCALLDATAOVERHEAD is a free data retrieval call binding the contract method 0x028f85f7. // -// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASCALLDATAOVERHEAD(opts *bind.CallOpts) (uint32, error) { +// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASCALLDATAOVERHEAD(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L2CrossDomainMessenger.contract.Call(opts, &out, "MIN_GAS_CALLDATA_OVERHEAD") if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -251,30 +251,30 @@ func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASCALLDATAOVERH // MINGASCALLDATAOVERHEAD is a free data retrieval call binding the contract method 0x028f85f7. // -// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) MINGASCALLDATAOVERHEAD() (uint32, error) { +// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) MINGASCALLDATAOVERHEAD() (uint64, error) { return _L2CrossDomainMessenger.Contract.MINGASCALLDATAOVERHEAD(&_L2CrossDomainMessenger.CallOpts) } // MINGASCALLDATAOVERHEAD is a free data retrieval call binding the contract method 0x028f85f7. // -// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) MINGASCALLDATAOVERHEAD() (uint32, error) { +// Solidity: function MIN_GAS_CALLDATA_OVERHEAD() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) MINGASCALLDATAOVERHEAD() (uint64, error) { return _L2CrossDomainMessenger.Contract.MINGASCALLDATAOVERHEAD(&_L2CrossDomainMessenger.CallOpts) } // MINGASCONSTANTOVERHEAD is a free data retrieval call binding the contract method 0x7dea7cc3. // -// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASCONSTANTOVERHEAD(opts *bind.CallOpts) (uint32, error) { +// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASCONSTANTOVERHEAD(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L2CrossDomainMessenger.contract.Call(opts, &out, "MIN_GAS_CONSTANT_OVERHEAD") if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -282,30 +282,30 @@ func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASCONSTANTOVERH // MINGASCONSTANTOVERHEAD is a free data retrieval call binding the contract method 0x7dea7cc3. // -// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) MINGASCONSTANTOVERHEAD() (uint32, error) { +// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) MINGASCONSTANTOVERHEAD() (uint64, error) { return _L2CrossDomainMessenger.Contract.MINGASCONSTANTOVERHEAD(&_L2CrossDomainMessenger.CallOpts) } // MINGASCONSTANTOVERHEAD is a free data retrieval call binding the contract method 0x7dea7cc3. // -// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) MINGASCONSTANTOVERHEAD() (uint32, error) { +// Solidity: function MIN_GAS_CONSTANT_OVERHEAD() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) MINGASCONSTANTOVERHEAD() (uint64, error) { return _L2CrossDomainMessenger.Contract.MINGASCONSTANTOVERHEAD(&_L2CrossDomainMessenger.CallOpts) } // MINGASDYNAMICOVERHEADDENOMINATOR is a free data retrieval call binding the contract method 0x0c568498. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASDYNAMICOVERHEADDENOMINATOR(opts *bind.CallOpts) (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASDYNAMICOVERHEADDENOMINATOR(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L2CrossDomainMessenger.contract.Call(opts, &out, "MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR") if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -313,30 +313,30 @@ func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASDYNAMICOVERHE // MINGASDYNAMICOVERHEADDENOMINATOR is a free data retrieval call binding the contract method 0x0c568498. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) MINGASDYNAMICOVERHEADDENOMINATOR() (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) MINGASDYNAMICOVERHEADDENOMINATOR() (uint64, error) { return _L2CrossDomainMessenger.Contract.MINGASDYNAMICOVERHEADDENOMINATOR(&_L2CrossDomainMessenger.CallOpts) } // MINGASDYNAMICOVERHEADDENOMINATOR is a free data retrieval call binding the contract method 0x0c568498. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) MINGASDYNAMICOVERHEADDENOMINATOR() (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) MINGASDYNAMICOVERHEADDENOMINATOR() (uint64, error) { return _L2CrossDomainMessenger.Contract.MINGASDYNAMICOVERHEADDENOMINATOR(&_L2CrossDomainMessenger.CallOpts) } // MINGASDYNAMICOVERHEADNUMERATOR is a free data retrieval call binding the contract method 0x2828d7e8. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASDYNAMICOVERHEADNUMERATOR(opts *bind.CallOpts) (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASDYNAMICOVERHEADNUMERATOR(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L2CrossDomainMessenger.contract.Call(opts, &out, "MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR") if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -344,30 +344,30 @@ func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) MINGASDYNAMICOVERHE // MINGASDYNAMICOVERHEADNUMERATOR is a free data retrieval call binding the contract method 0x2828d7e8. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) MINGASDYNAMICOVERHEADNUMERATOR() (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) MINGASDYNAMICOVERHEADNUMERATOR() (uint64, error) { return _L2CrossDomainMessenger.Contract.MINGASDYNAMICOVERHEADNUMERATOR(&_L2CrossDomainMessenger.CallOpts) } // MINGASDYNAMICOVERHEADNUMERATOR is a free data retrieval call binding the contract method 0x2828d7e8. // -// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) MINGASDYNAMICOVERHEADNUMERATOR() (uint32, error) { +// Solidity: function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() view returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) MINGASDYNAMICOVERHEADNUMERATOR() (uint64, error) { return _L2CrossDomainMessenger.Contract.MINGASDYNAMICOVERHEADNUMERATOR(&_L2CrossDomainMessenger.CallOpts) } // BaseGas is a free data retrieval call binding the contract method 0xb28ade25. // -// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) BaseGas(opts *bind.CallOpts, _message []byte, _minGasLimit uint32) (uint32, error) { +// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) BaseGas(opts *bind.CallOpts, _message []byte, _minGasLimit uint32) (uint64, error) { var out []interface{} err := _L2CrossDomainMessenger.contract.Call(opts, &out, "baseGas", _message, _minGasLimit) if err != nil { - return *new(uint32), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -375,15 +375,15 @@ func (_L2CrossDomainMessenger *L2CrossDomainMessengerCaller) BaseGas(opts *bind. // BaseGas is a free data retrieval call binding the contract method 0xb28ade25. // -// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) BaseGas(_message []byte, _minGasLimit uint32) (uint32, error) { +// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerSession) BaseGas(_message []byte, _minGasLimit uint32) (uint64, error) { return _L2CrossDomainMessenger.Contract.BaseGas(&_L2CrossDomainMessenger.CallOpts, _message, _minGasLimit) } // BaseGas is a free data retrieval call binding the contract method 0xb28ade25. // -// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint32) -func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) BaseGas(_message []byte, _minGasLimit uint32) (uint32, error) { +// Solidity: function baseGas(bytes _message, uint32 _minGasLimit) pure returns(uint64) +func (_L2CrossDomainMessenger *L2CrossDomainMessengerCallerSession) BaseGas(_message []byte, _minGasLimit uint32) (uint64, error) { return _L2CrossDomainMessenger.Contract.BaseGas(&_L2CrossDomainMessenger.CallOpts, _message, _minGasLimit) } diff --git a/op-bindings/bindings/l2crossdomainmessenger_more.go b/op-bindings/bindings/l2crossdomainmessenger_more.go index 3c3fd2ed8150d..06e9667ecc5a5 100644 --- a/op-bindings/bindings/l2crossdomainmessenger_more.go +++ b/op-bindings/bindings/l2crossdomainmessenger_more.go @@ -9,11 +9,11 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const L2CrossDomainMessengerStorageLayoutJSON = "{\"storage\":[{\"astId\":24726,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":27112,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_initialized\",\"offset\":20,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":27115,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_initializing\",\"offset\":21,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":27726,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":26984,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":27104,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":27277,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_paused\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_bool\"},{\"astId\":27382,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":27397,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_status\",\"offset\":0,\"slot\":\"151\",\"type\":\"t_uint256\"},{\"astId\":27441,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"152\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":24778,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_201_0_32\",\"offset\":0,\"slot\":\"201\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24783,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_202_0_32\",\"offset\":0,\"slot\":\"202\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24788,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"successfulMessages\",\"offset\":0,\"slot\":\"203\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24791,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"xDomainMsgSender\",\"offset\":0,\"slot\":\"204\",\"type\":\"t_address\"},{\"astId\":24794,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"msgNonce\",\"offset\":0,\"slot\":\"205\",\"type\":\"t_uint240\"},{\"astId\":24799,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"receivedMessages\",\"offset\":0,\"slot\":\"206\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24804,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"207\",\"type\":\"t_array(t_uint256)42_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)42_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[42]\",\"numberOfBytes\":\"1344\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"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\"}}}" +const L2CrossDomainMessengerStorageLayoutJSON = "{\"storage\":[{\"astId\":24811,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":27200,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_initialized\",\"offset\":20,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":27203,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_initializing\",\"offset\":21,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":27814,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":27072,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":27192,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":27365,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_paused\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_bool\"},{\"astId\":27470,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":27485,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_status\",\"offset\":0,\"slot\":\"151\",\"type\":\"t_uint256\"},{\"astId\":27529,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"152\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":24863,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_201_0_32\",\"offset\":0,\"slot\":\"201\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24868,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_202_0_32\",\"offset\":0,\"slot\":\"202\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24873,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"successfulMessages\",\"offset\":0,\"slot\":\"203\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24876,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"xDomainMsgSender\",\"offset\":0,\"slot\":\"204\",\"type\":\"t_address\"},{\"astId\":24879,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"msgNonce\",\"offset\":0,\"slot\":\"205\",\"type\":\"t_uint240\"},{\"astId\":24884,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"receivedMessages\",\"offset\":0,\"slot\":\"206\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":24889,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"207\",\"type\":\"t_array(t_uint256)42_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)42_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[42]\",\"numberOfBytes\":\"1344\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"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\"}}}" var L2CrossDomainMessengerStorageLayout = new(solc.StorageLayout) -var L2CrossDomainMessengerDeployedBin = "0x6080604052600436106101755760003560e01c80638129fc1c116100cb578063b28ade251161007f578063ecc7042811610059578063ecc70428146103f2578063f2fde38b14610457578063f69f81511461047757600080fd5b8063b28ade251461038b578063d764ad0b146103ab578063db505d80146103be57600080fd5b80638da5cb5b116100b05780638da5cb5b146102fd578063a711986914610328578063b1b1b2091461035b57600080fd5b80638129fc1c146102d35780638456cb59146102e857600080fd5b80633f827a5a1161012d5780636e296e45116101075780636e296e451461026d578063715018a6146102a75780637dea7cc3146102bc57600080fd5b80633f827a5a146101ff57806354fd4d50146102275780635c975abb1461024957600080fd5b80632828d7e81161015e5780632828d7e8146101bf5780633dbb202b146101d55780633f4ba83a146101ea57600080fd5b8063028f85f71461017a5780630c568498146101a9575b600080fd5b34801561018657600080fd5b5061018f601081565b60405163ffffffff90911681526020015b60405180910390f35b3480156101b557600080fd5b5061018f6103e881565b3480156101cb57600080fd5b5061018f6103f881565b6101e86101e3366004611cc9565b6104a7565b005b3480156101f657600080fd5b506101e8610711565b34801561020b57600080fd5b50610214600181565b60405161ffff90911681526020016101a0565b34801561023357600080fd5b5061023c610723565b6040516101a09190611da8565b34801561025557600080fd5b5060655460ff165b60405190151581526020016101a0565b34801561027957600080fd5b506102826107c6565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a0565b3480156102b357600080fd5b506101e86108b2565b3480156102c857600080fd5b5061018f62030d4081565b3480156102df57600080fd5b506101e86108c4565b3480156102f457600080fd5b506101e8610ac1565b34801561030957600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610282565b34801561033457600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610282565b34801561036757600080fd5b5061025d610376366004611dc2565b60cb6020526000908152604090205460ff1681565b34801561039757600080fd5b5061018f6103a6366004611ddb565b610ad1565b6101e86103b9366004611e2f565b610b17565b3480156103ca57600080fd5b506102827f000000000000000000000000000000000000000000000000000000000000000081565b3480156103fe57600080fd5b5061044960cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a0565b34801561046357600080fd5b506101e8610472366004611eb1565b6111f9565b34801561048357600080fd5b5061025d610492366004611dc2565b60ce6020526000908152604090205460ff1681565b6105e67f00000000000000000000000000000000000000000000000000000000000000006104d6858585610ad1565b63ffffffff16347fd764ad0b0000000000000000000000000000000000000000000000000000000061054860cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105649796959493929190611f15565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526112c9565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561066b60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b8660405161067d959493929190611f74565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b610719611357565b6107216113d8565b565b606061074e7f0000000000000000000000000000000000000000000000000000000000000000611455565b6107777f0000000000000000000000000000000000000000000000000000000000000000611455565b6107a07f0000000000000000000000000000000000000000000000000000000000000000611455565b6040516020016107b293929190611fc2565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610895576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6108ba611357565b610721600061158a565b6000547501000000000000000000000000000000000000000000900460ff161580801561090f575060005460017401000000000000000000000000000000000000000090910460ff16105b806109415750303b158015610941575060005474010000000000000000000000000000000000000000900460ff166001145b6109cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161088c565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610a5357600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610a5b611601565b8015610abe57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610ac9611357565b6107216116f8565b600062030d40610ae2601085612067565b6103e8610af16103f886612067565b610afb91906120c2565b610b0591906120e5565b610b0f91906120e5565b949350505050565b600260975403610b83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161088c565b6002609755610b90611753565b60f087901c60018114610c4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605560248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2031206d657373616765732061726520737570706f72746564206166746560648201527f722074686520426564726f636b20757067726164650000000000000000000000608482015260a40161088c565b6000610c91898989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117c092505050565b905073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef330181167f000000000000000000000000000000000000000000000000000000000000000090911603610d0a57853414610d0557610d0561210d565b610e5c565b3415610dbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161088c565b600081815260ce602052604090205460ff16610e5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161088c565b610e65876117e3565b15610f18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161088c565b600081815260cb602052604090205460ff1615610fb7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161088c565b610fc361afc88661213c565b5a1015611052576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a20696e737566666963696560448201527f6e742067617320746f2072656c6179206d657373616765000000000000000000606482015260840161088c565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006110ee886110a661138861afc8612154565b5a6110b19190612154565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061183892505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560010361118957600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26111e8565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a25b505060016097555050505050505050565b611201611357565b73ffffffffffffffffffffffffffffffffffffffff81166112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161088c565b610abe8161158a565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fc2b3e5ac0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000169063c2b3e5ac90849061131f9088908890879060040161216b565b6000604051808303818588803b15801561133857600080fd5b505af115801561134c573d6000803e3d6000fd5b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161088c565b6113e0611852565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60608160000361149857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156114c257806114ac816121b3565b91506114bb9050600a836121eb565b915061149c565b60008167ffffffffffffffff8111156114dd576114dd6121ff565b6040519080825280601f01601f191660200182016040528015611507576020820181803683370190505b5090505b8415610b0f5761151c600183612154565b9150611529600a8661222e565b61153490603061213c565b60f81b81838151811061154957611549612242565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611583600a866121eb565b945061150b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000547501000000000000000000000000000000000000000000900460ff166116ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556116e06118be565b6116e8611969565b6116f0611a1d565b610721611af2565b611700611753565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861142b3390565b60655460ff1615610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161088c565b60006117d0878787878787611ba4565b8051906020012090509695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611832575073ffffffffffffffffffffffffffffffffffffffff8216734200000000000000000000000000000000000016145b92915050565b600080600080845160208601878a8af19695505050505050565b60655460ff16610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161088c565b6000547501000000000000000000000000000000000000000000900460ff16610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b6000547501000000000000000000000000000000000000000000900460ff16611a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b6107213361158a565b6000547501000000000000000000000000000000000000000000900460ff16611ac8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000547501000000000000000000000000000000000000000000900460ff16611b9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088c565b6001609755565b6060868686868686604051602401611bc196959493929190612271565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c6757600080fd5b919050565b60008083601f840112611c7e57600080fd5b50813567ffffffffffffffff811115611c9657600080fd5b602083019150836020828501011115611cae57600080fd5b9250929050565b803563ffffffff81168114611c6757600080fd5b60008060008060608587031215611cdf57600080fd5b611ce885611c43565b9350602085013567ffffffffffffffff811115611d0457600080fd5b611d1087828801611c6c565b9094509250611d23905060408601611cb5565b905092959194509250565b60005b83811015611d49578181015183820152602001611d31565b83811115611d58576000848401525b50505050565b60008151808452611d76816020860160208601611d2e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611dbb6020830184611d5e565b9392505050565b600060208284031215611dd457600080fd5b5035919050565b600080600060408486031215611df057600080fd5b833567ffffffffffffffff811115611e0757600080fd5b611e1386828701611c6c565b9094509250611e26905060208501611cb5565b90509250925092565b600080600080600080600060c0888a031215611e4a57600080fd5b87359650611e5a60208901611c43565b9550611e6860408901611c43565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611e9257600080fd5b611e9e8a828b01611c6c565b989b979a50959850939692959293505050565b600060208284031215611ec357600080fd5b611dbb82611c43565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611f6760c083018486611ecc565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611fa4608083018688611ecc565b905083604083015263ffffffff831660608301529695505050505050565b60008451611fd4818460208901611d2e565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612010816001850160208a01611d2e565b6001920191820152835161202b816002840160208801611d2e565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff8083168185168183048111821515161561208a5761208a612038565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600063ffffffff808416806120d9576120d9612093565b92169190910492915050565b600063ffffffff80831681851680830382111561210457612104612038565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000821982111561214f5761214f612038565b500190565b60008282101561216657612166612038565b500390565b73ffffffffffffffffffffffffffffffffffffffff8416815267ffffffffffffffff831660208201526060604082015260006121aa6060830184611d5e565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121e4576121e4612038565b5060010190565b6000826121fa576121fa612093565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008261223d5761223d612093565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526122bc60c0830184611d5e565b9897505050505050505056fea164736f6c634300080f000a" +var L2CrossDomainMessengerDeployedBin = "0x6080604052600436106101755760003560e01c80638129fc1c116100cb578063b28ade251161007f578063ecc7042811610059578063ecc70428146103f6578063f2fde38b1461045b578063f69f81511461047b57600080fd5b8063b28ade251461038f578063d764ad0b146103af578063db505d80146103c257600080fd5b80638da5cb5b116100b05780638da5cb5b14610301578063a71198691461032c578063b1b1b2091461035f57600080fd5b80638129fc1c146102d75780638456cb59146102ec57600080fd5b80633f827a5a1161012d5780636e296e45116101075780636e296e4514610271578063715018a6146102ab5780637dea7cc3146102c057600080fd5b80633f827a5a1461020357806354fd4d501461022b5780635c975abb1461024d57600080fd5b80632828d7e81161015e5780632828d7e8146101c35780633dbb202b146101d95780633f4ba83a146101ee57600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f6103e881565b3480156101cf57600080fd5b5061018f6103f881565b6101ec6101e7366004611ccd565b6104ab565b005b3480156101fa57600080fd5b506101ec61070f565b34801561020f57600080fd5b50610218600181565b60405161ffff90911681526020016101a4565b34801561023757600080fd5b50610240610721565b6040516101a49190611dac565b34801561025957600080fd5b5060655460ff165b60405190151581526020016101a4565b34801561027d57600080fd5b506102866107c4565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b3480156102b757600080fd5b506101ec6108b0565b3480156102cc57600080fd5b5061018f62030d4081565b3480156102e357600080fd5b506101ec6108c2565b3480156102f857600080fd5b506101ec610abf565b34801561030d57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610286565b34801561033857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610286565b34801561036b57600080fd5b5061026161037a366004611dc6565b60cb6020526000908152604090205460ff1681565b34801561039b57600080fd5b5061018f6103aa366004611ddf565b610acf565b6101ec6103bd366004611e33565b610b1b565b3480156103ce57600080fd5b506102867f000000000000000000000000000000000000000000000000000000000000000081565b34801561040257600080fd5b5061044d60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b34801561046757600080fd5b506101ec610476366004611eb5565b6111fd565b34801561048757600080fd5b50610261610496366004611dc6565b60ce6020526000908152604090205460ff1681565b6105e47f00000000000000000000000000000000000000000000000000000000000000006104da858585610acf565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061054660cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105629796959493929190611f19565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526112cd565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561066960cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b8660405161067b959493929190611f78565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b61071761135b565b61071f6113dc565b565b606061074c7f0000000000000000000000000000000000000000000000000000000000000000611459565b6107757f0000000000000000000000000000000000000000000000000000000000000000611459565b61079e7f0000000000000000000000000000000000000000000000000000000000000000611459565b6040516020016107b093929190611fc6565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6108b861135b565b61071f600061158e565b6000547501000000000000000000000000000000000000000000900460ff161580801561090d575060005460017401000000000000000000000000000000000000000090910460ff16105b8061093f5750303b15801561093f575060005474010000000000000000000000000000000000000000900460ff166001145b6109cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161088a565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610a5157600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610a59611605565b8015610abc57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610ac761135b565b61071f6116fc565b600062030d40610ae060108561206b565b6103e8610af56103f863ffffffff871661206b565b610aff91906120ca565b610b0991906120f1565b610b1391906120f1565b949350505050565b600260975403610b87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161088a565b6002609755610b94611757565b60f087901c60018114610c4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605560248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2031206d657373616765732061726520737570706f72746564206166746560648201527f722074686520426564726f636b20757067726164650000000000000000000000608482015260a40161088a565b6000610c95898989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117c492505050565b905073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef330181167f000000000000000000000000000000000000000000000000000000000000000090911603610d0e57853414610d0957610d0961211d565b610e60565b3415610dc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161088a565b600081815260ce602052604090205460ff16610e60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161088a565b610e69876117e7565b15610f1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161088a565b600081815260cb602052604090205460ff1615610fbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161088a565b610fc761afc88661214c565b5a1015611056576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a20696e737566666963696560448201527f6e742067617320746f2072656c6179206d657373616765000000000000000000606482015260840161088a565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006110f2886110aa61138861afc8612164565b5a6110b59190612164565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061183c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560010361118d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26111ec565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a25b505060016097555050505050505050565b61120561135b565b73ffffffffffffffffffffffffffffffffffffffff81166112a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161088a565b610abc8161158e565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fc2b3e5ac0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000169063c2b3e5ac9084906113239088908890879060040161217b565b6000604051808303818588803b15801561133c57600080fd5b505af1158015611350573d6000803e3d6000fd5b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff16331461071f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161088a565b6113e4611856565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60608160000361149c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156114c657806114b0816121c3565b91506114bf9050600a836121fb565b91506114a0565b60008167ffffffffffffffff8111156114e1576114e161220f565b6040519080825280601f01601f19166020018201604052801561150b576020820181803683370190505b5090505b8415610b1357611520600183612164565b915061152d600a8661223e565b61153890603061214c565b60f81b81838151811061154d5761154d612252565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611587600a866121fb565b945061150f565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000547501000000000000000000000000000000000000000000900460ff166116b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556116e46118c2565b6116ec61196d565b6116f4611a21565b61071f611af6565b611704611757565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861142f3390565b60655460ff161561071f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161088a565b60006117d4878787878787611ba8565b8051906020012090509695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611836575073ffffffffffffffffffffffffffffffffffffffff8216734200000000000000000000000000000000000016145b92915050565b600080600080845160208601878a8af19695505050505050565b60655460ff1661071f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161088a565b6000547501000000000000000000000000000000000000000000900460ff1661071f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b6000547501000000000000000000000000000000000000000000900460ff16611a18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b61071f3361158e565b6000547501000000000000000000000000000000000000000000900460ff16611acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000547501000000000000000000000000000000000000000000900460ff16611ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161088a565b6001609755565b6060868686868686604051602401611bc596959493929190612281565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c6b57600080fd5b919050565b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b803563ffffffff81168114611c6b57600080fd5b60008060008060608587031215611ce357600080fd5b611cec85611c47565b9350602085013567ffffffffffffffff811115611d0857600080fd5b611d1487828801611c70565b9094509250611d27905060408601611cb9565b905092959194509250565b60005b83811015611d4d578181015183820152602001611d35565b83811115611d5c576000848401525b50505050565b60008151808452611d7a816020860160208601611d32565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611dbf6020830184611d62565b9392505050565b600060208284031215611dd857600080fd5b5035919050565b600080600060408486031215611df457600080fd5b833567ffffffffffffffff811115611e0b57600080fd5b611e1786828701611c70565b9094509250611e2a905060208501611cb9565b90509250925092565b600080600080600080600060c0888a031215611e4e57600080fd5b87359650611e5e60208901611c47565b9550611e6c60408901611c47565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611e9657600080fd5b611ea28a828b01611c70565b989b979a50959850939692959293505050565b600060208284031215611ec757600080fd5b611dbf82611c47565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611f6b60c083018486611ed0565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611fa8608083018688611ed0565b905083604083015263ffffffff831660608301529695505050505050565b60008451611fd8818460208901611d32565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612014816001850160208a01611d32565b6001920191820152835161202f816002840160208801611d32565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff808316818516818304811182151516156120925761209261203c565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff808416806120e5576120e561209b565b92169190910492915050565b600067ffffffffffffffff8083168185168083038211156121145761211461203c565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000821982111561215f5761215f61203c565b500190565b6000828210156121765761217661203c565b500390565b73ffffffffffffffffffffffffffffffffffffffff8416815267ffffffffffffffff831660208201526060604082015260006121ba6060830184611d62565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121f4576121f461203c565b5060010190565b60008261220a5761220a61209b565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008261224d5761224d61209b565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526122cc60c0830184611d62565b9897505050505050505056fea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(L2CrossDomainMessengerStorageLayoutJSON), L2CrossDomainMessengerStorageLayout); err != nil { diff --git a/op-bindings/bindings/l2outputoracle.go b/op-bindings/bindings/l2outputoracle.go index 1f1f6193396c8..a8404096f9275 100644 --- a/op-bindings/bindings/l2outputoracle.go +++ b/op-bindings/bindings/l2outputoracle.go @@ -36,8 +36,8 @@ type TypesOutputProposal struct { // L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. var L2OutputOracleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_proposer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"OutputDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"OutputProposed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousProposer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newProposer\",\"type\":\"address\"}],\"name\":\"ProposerChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_NUMBER\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newProposer\",\"type\":\"address\"}],\"name\":\"changeProposer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"computeL2Timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.OutputProposal\",\"name\":\"_proposal\",\"type\":\"tuple\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.OutputProposal\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_proposer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"proposeL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b506040516200235d3803806200235d83398101604081905262000035916200060b565b6000608081905260a052600160c05242841115620000ce5760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a4015b60405180910390fd5b60e0889052610100869052610120859052610140849052610160839052620000f98786848462000107565b50505050505050506200067d565b600054610100900460ff1615808015620001285750600054600160ff909116105b806200015857506200014530620002fb60201b620013da1760201c565b15801562000158575060005460ff166001145b620001bd5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000c5565b6000805460ff191660011790558015620001e1576000805461ff0019166101001790555b816001600160a01b0316836001600160a01b031603620002595760405162461bcd60e51b815260206004820152603860248201526000805160206200233d83398151915260448201527f6265207468652073616d6520617320746865206f776e657200000000000000006064820152608401620000c5565b60408051808201825286815242602080830191825260008881526067909152929092209051815590516001909101556066849055620002976200030a565b620002a28362000372565b620002ad82620004d9565b8015620002f4576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b03163b151590565b600054610100900460ff16620003665760405162461bcd60e51b815260206004820152602b60248201526000805160206200231d83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000c5565b620003706200052b565b565b6200037c62000592565b6001600160a01b038116620003fa5760405162461bcd60e51b815260206004820152603760248201527f4c324f75747075744f7261636c653a206e65772070726f706f7365722063616e60448201527f6e6f7420626520746865207a65726f20616464726573730000000000000000006064820152608401620000c5565b6033546001600160a01b03166001600160a01b0316816001600160a01b0316036200047d5760405162461bcd60e51b815260206004820152603860248201526000805160206200233d83398151915260448201527f6265207468652073616d6520617320746865206f776e657200000000000000006064820152608401620000c5565b6065546040516001600160a01b038084169216907f3d7728dc2838bb794606bd89f5a37930830b32060f69ee929bbfc59b669024dd90600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620005875760405162461bcd60e51b815260206004820152602b60248201526000805160206200231d83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000c5565b6200037033620004d9565b6033546001600160a01b03163314620003705760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000c5565b80516001600160a01b03811681146200060657600080fd5b919050565b600080600080600080600080610100898b0312156200062957600080fd5b885197506020890151965060408901519550606089015194506080890151935060a089015192506200065e60c08a01620005ee565b91506200066e60e08a01620005ee565b90509295985092959890939650565b60805160a05160c05160e05161010051610120516101405161016051611bf4620007296000396000818161013f0152610fcc0152600081816101a801526110250152600081816101f201528181610cbe01528181610dba01528181610ef60152610ff00152600061034b0152600081816102260152818161061001528181610d9601528181610df901526112ea015260006106950152600061066c015260006106430152611bf46000f3fe6080604052600436106101285760003560e01c80638da5cb5b116100a5578063a8e4fb9011610074578063d20b1a5111610059578063d20b1a51146103ba578063dcec3348146103da578063f2fde38b146103ef57600080fd5b8063a8e4fb901461036d578063d1de856c1461039a57600080fd5b80638da5cb5b1461029f5780639aaab648146102eb578063a25ae557146102fe578063a4771aad1461033957600080fd5b80634ab65d73116100fc57806354fd4d50116100e157806354fd4d5014610248578063715018a61461026a57806372d5fe211461027f57600080fd5b80634ab65d73146101e0578063529933df1461021457600080fd5b80622134cc1461012d578063093b3d901461017457806320e9fcd4146101965780634599c788146101ca575b600080fd5b34801561013957600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561018057600080fd5b5061019461018f366004611845565b61040f565b005b3480156101a257600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b3480156101d657600080fd5b5061016160665481565b3480156101ec57600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b34801561022057600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b34801561025457600080fd5b5061025d61063c565b60405161016b91906118eb565b34801561027657600080fd5b506101946106df565b34801561028b57600080fd5b5061019461029a366004611965565b6106f3565b3480156102ab57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016b565b6101946102f9366004611987565b6108ff565b34801561030a57600080fd5b5061031e6103193660046119b9565b610ca8565b6040805182518152602092830151928101929092520161016b565b34801561034557600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b34801561037957600080fd5b506065546102c69073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a657600080fd5b506101616103b53660046119b9565b610ef2565b3480156103c657600080fd5b506101946103d53660046119d2565b61104f565b3480156103e657600080fd5b506101616112e6565b3480156103fb57600080fd5b5061019461040a366004611965565b61131b565b6104176113f6565b6066546000908152606760209081526040918290208251808401909352805480845260019091015491830191909152825114610500576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604f60248201527f4c324f75747075744f7261636c653a206f757470757420726f6f7420746f206460448201527f656c65746520646f6573206e6f74206d6174636820746865206c61746573742060648201527f6f75747075742070726f706f73616c0000000000000000000000000000000000608482015260a4015b60405180910390fd5b80602001518260200151146105bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f4c324f75747075744f7261636c653a2074696d657374616d7020746f2064656c60448201527f65746520646f6573206e6f74206d6174636820746865206c6174657374206f7560648201527f747075742070726f706f73616c00000000000000000000000000000000000000608482015260a4016104f7565b606654602082015182516040517f11e942315215fbc11bf574b22ca610d001e704d870a2307833c188d31600b5c690600090a46066805460009081526067602052604081208181556001015554610635907f000000000000000000000000000000000000000000000000000000000000000090611a47565b6066555050565b60606106677f0000000000000000000000000000000000000000000000000000000000000000611477565b6106907f0000000000000000000000000000000000000000000000000000000000000000611477565b6106b97f0000000000000000000000000000000000000000000000000000000000000000611477565b6040516020016106cb93929190611a5e565b604051602081830303815290604052905090565b6106e76113f6565b6106f160006115ac565b565b6106fb6113f6565b73ffffffffffffffffffffffffffffffffffffffff811661079e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324f75747075744f7261636c653a206e65772070726f706f7365722063616e60448201527f6e6f7420626520746865207a65726f206164647265737300000000000000000060648201526084016104f7565b60335473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610871576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4c324f75747075744f7261636c653a2070726f706f7365722063616e6e6f742060448201527f6265207468652073616d6520617320746865206f776e6572000000000000000060648201526084016104f7565b60655460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f3d7728dc2838bb794606bd89f5a37930830b32060f69ee929bbfc59b669024dd90600090a3606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60655473ffffffffffffffffffffffffffffffffffffffff1633146109a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324f75747075744f7261636c653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642062792070726f706f73657200000000000000000060648201526084016104f7565b6109ae6112e6565b8314610a62576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a4016104f7565b42610a6c84610ef2565b10610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e20746865206675747572650000000000000000000060648201526084016104f7565b83610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f206861736800000000000060648201526084016104f7565b8115610c425781814014610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b6861736820646f6573206e60448201527f6f74206d6174636820746865206861736820617420746865206578706563746560648201527f6420686569676874000000000000000000000000000000000000000000000000608482015260a4016104f7565b6040805180820182528581524260208083018281526000888152606790925284822093518455516001909301929092556066869055915185929187917fc120f5e881491e6e212befa39e36b8f57d5eca31915f2e5d60a420f418caa6df9190a450505050565b60408051808201909152600080825260208201527f0000000000000000000000000000000000000000000000000000000000000000821015610d92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d6265722063616e60448201527f6e6f74206265206c657373207468616e20746865207374617274696e6720626c60648201527f6f636b206e756d6265722e000000000000000000000000000000000000000000608482015260a4016104f7565b60007f0000000000000000000000000000000000000000000000000000000000000000610ddf7f000000000000000000000000000000000000000000000000000000000000000085611a47565b610de99190611b03565b905060008115610e2c57610e1d827f0000000000000000000000000000000000000000000000000000000000000000611a47565b610e279085611b17565b610e2e565b835b600081815260676020908152604091829020825180840190935280548084526001909101549183019190915291925090610eea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a204e6f206f757470757420666f756e642060448201527f666f72207468617420626c6f636b206e756d6265722e0000000000000000000060648201526084016104f7565b949350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000821015610fca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605360248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f742062652067726561746572207468616e206f7220657175616c20746f20737460648201527f617274696e6720626c6f636b206e756d62657200000000000000000000000000608482015260a4016104f7565b7f00000000000000000000000000000000000000000000000000000000000000006110157f000000000000000000000000000000000000000000000000000000000000000084611a47565b61101f9190611b2f565b611049907f0000000000000000000000000000000000000000000000000000000000000000611b17565b92915050565b600054610100900460ff161580801561106f5750600054600160ff909116105b806110895750303b158015611089575060005460ff166001145b611115576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f7565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561117357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4c324f75747075744f7261636c653a2070726f706f7365722063616e6e6f742060448201527f6265207468652073616d6520617320746865206f776e6572000000000000000060648201526084016104f7565b6040805180820182528681524260208083019182526000888152606790915292909220905181559051600190910155606684905561126a611623565b611273836106f3565b61127c826115ac565b80156112df57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006066546113169190611b17565b905090565b6113236113f6565b60655473ffffffffffffffffffffffffffffffffffffffff908116908216036113ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4c324f75747075744f7261636c653a206f776e65722063616e6e6f742062652060448201527f7468652073616d65206173207468652070726f706f736572000000000000000060648201526084016104f7565b6113d7816116c2565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f7565b6060816000036114ba57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156114e457806114ce81611b6c565b91506114dd9050600a83611ba4565b91506114be565b60008167ffffffffffffffff8111156114ff576114ff611816565b6040519080825280601f01601f191660200182016040528015611529576020820181803683370190505b5090505b8415610eea5761153e600183611a47565b915061154b600a86611b03565b611556906030611b17565b60f81b81838151811061156b5761156b611bb8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506115a5600a86611ba4565b945061152d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166116ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104f7565b6106f1611776565b6116ca6113f6565b73ffffffffffffffffffffffffffffffffffffffff811661176d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104f7565b6113d7816115ac565b600054610100900460ff1661180d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104f7565b6106f1336115ac565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006040828403121561185757600080fd5b6040516040810181811067ffffffffffffffff821117156118a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823581526020928301359281019290925250919050565b60005b838110156118d65781810151838201526020016118be565b838111156118e5576000848401525b50505050565b602081526000825180602084015261190a8160408501602087016118bb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461196057600080fd5b919050565b60006020828403121561197757600080fd5b6119808261193c565b9392505050565b6000806000806080858703121561199d57600080fd5b5050823594602084013594506040840135936060013592509050565b6000602082840312156119cb57600080fd5b5035919050565b600080600080608085870312156119e857600080fd5b84359350602085013592506119ff6040860161193c565b9150611a0d6060860161193c565b905092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611a5957611a59611a18565b500390565b60008451611a708184602089016118bb565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611aac816001850160208a016118bb565b60019201918201528351611ac78160028401602088016118bb565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611b1257611b12611ad4565b500690565b60008219821115611b2a57611b2a611a18565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611b6757611b67611a18565b500290565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b9d57611b9d611a18565b5060010190565b600082611bb357611bb3611ad4565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f7420694c324f75747075744f7261636c653a2070726f706f7365722063616e6e6f7420", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_proposer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"OutputDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"OutputProposed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousProposer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newProposer\",\"type\":\"address\"}],\"name\":\"ProposerChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_NUMBER\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newProposer\",\"type\":\"address\"}],\"name\":\"changeProposer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"computeL2Timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.OutputProposal\",\"name\":\"_proposal\",\"type\":\"tuple\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.OutputProposal\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_proposer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"proposeL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101806040523480156200001257600080fd5b506040516200237038038062002370833981016040819052620000359162000609565b6000608081905260a052600160c05242841115620000ce5760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a4015b60405180910390fd5b60e0889052610100869052610120859052610140849052610160839052620000f887838362000106565b50505050505050506200067b565b600054610100900460ff1615808015620001275750600054600160ff909116105b806200015757506200014430620002f960201b620013f61760201c565b15801562000157575060005460ff166001145b620001bc5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000c5565b6000805460ff191660011790558015620001e0576000805461ff0019166101001790555b816001600160a01b0316836001600160a01b031603620002585760405162461bcd60e51b815260206004820152603860248201526000805160206200235083398151915260448201527f6265207468652073616d6520617320746865206f776e657200000000000000006064820152608401620000c5565b604080518082018252858152426020808301918252610120516000818152606790925293902091518255516001909101556066556200029662000308565b620002a18362000370565b620002ac82620004d7565b8015620002f3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff16620003645760405162461bcd60e51b815260206004820152602b60248201526000805160206200233083398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000c5565b6200036e62000529565b565b6200037a62000590565b6001600160a01b038116620003f85760405162461bcd60e51b815260206004820152603760248201527f4c324f75747075744f7261636c653a206e65772070726f706f7365722063616e60448201527f6e6f7420626520746865207a65726f20616464726573730000000000000000006064820152608401620000c5565b6033546001600160a01b03166001600160a01b0316816001600160a01b0316036200047b5760405162461bcd60e51b815260206004820152603860248201526000805160206200235083398151915260448201527f6265207468652073616d6520617320746865206f776e657200000000000000006064820152608401620000c5565b6065546040516001600160a01b038084169216907f3d7728dc2838bb794606bd89f5a37930830b32060f69ee929bbfc59b669024dd90600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620005855760405162461bcd60e51b815260206004820152602b60248201526000805160206200233083398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000c5565b6200036e33620004d7565b6033546001600160a01b031633146200036e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000c5565b80516001600160a01b03811681146200060457600080fd5b919050565b600080600080600080600080610100898b0312156200062757600080fd5b885197506020890151965060408901519550606089015194506080890151935060a089015192506200065c60c08a01620005ec565b91506200066c60e08a01620005ec565b90509295985092959890939650565b60805160a05160c05160e05161010051610120516101405161016051611c026200072e6000396000818161013f015261127f0152600081816101a801526112d80152600081816101f201528181610af501528181610f710152818161106d015281816111a901526112a30152600061036b0152600081816102260152818161061001528181611049015281816110ac0152611306015260006106950152600061066c015260006106430152611c026000f3fe6080604052600436106101285760003560e01c806388b117b3116100a5578063a4771aad11610074578063d1de856c11610059578063d1de856c146103ba578063dcec3348146103da578063f2fde38b146103ef57600080fd5b8063a4771aad14610359578063a8e4fb901461038d57600080fd5b806388b117b31461029f5780638da5cb5b146102bf5780639aaab6481461030b578063a25ae5571461031e57600080fd5b80634ab65d73116100fc57806354fd4d50116100e157806354fd4d5014610248578063715018a61461026a57806372d5fe211461027f57600080fd5b80634ab65d73146101e0578063529933df1461021457600080fd5b80622134cc1461012d578063093b3d901461017457806320e9fcd4146101965780634599c788146101ca575b600080fd5b34801561013957600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561018057600080fd5b5061019461018f366004611861565b61040f565b005b3480156101a257600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b3480156101d657600080fd5b5061016160665481565b3480156101ec57600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b34801561022057600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b34801561025457600080fd5b5061025d61063c565b60405161016b9190611903565b34801561027657600080fd5b506101946106df565b34801561028b57600080fd5b5061019461029a36600461197d565b6106f3565b3480156102ab57600080fd5b506101946102ba36600461199f565b6108ff565b3480156102cb57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016b565b6101946103193660046119db565b610bb2565b34801561032a57600080fd5b5061033e610339366004611a0d565b610f5b565b6040805182518152602092830151928101929092520161016b565b34801561036557600080fd5b506101617f000000000000000000000000000000000000000000000000000000000000000081565b34801561039957600080fd5b506065546102e69073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103c657600080fd5b506101616103d5366004611a0d565b6111a5565b3480156103e657600080fd5b50610161611302565b3480156103fb57600080fd5b5061019461040a36600461197d565b611337565b610417611412565b6066546000908152606760209081526040918290208251808401909352805480845260019091015491830191909152825114610500576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604f60248201527f4c324f75747075744f7261636c653a206f757470757420726f6f7420746f206460448201527f656c65746520646f6573206e6f74206d6174636820746865206c61746573742060648201527f6f75747075742070726f706f73616c0000000000000000000000000000000000608482015260a4015b60405180910390fd5b80602001518260200151146105bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f4c324f75747075744f7261636c653a2074696d657374616d7020746f2064656c60448201527f65746520646f6573206e6f74206d6174636820746865206c6174657374206f7560648201527f747075742070726f706f73616c00000000000000000000000000000000000000608482015260a4016104f7565b606654602082015182516040517f11e942315215fbc11bf574b22ca610d001e704d870a2307833c188d31600b5c690600090a46066805460009081526067602052604081208181556001015554610635907f000000000000000000000000000000000000000000000000000000000000000090611a55565b6066555050565b60606106677f0000000000000000000000000000000000000000000000000000000000000000611493565b6106907f0000000000000000000000000000000000000000000000000000000000000000611493565b6106b97f0000000000000000000000000000000000000000000000000000000000000000611493565b6040516020016106cb93929190611a6c565b604051602081830303815290604052905090565b6106e7611412565b6106f160006115c8565b565b6106fb611412565b73ffffffffffffffffffffffffffffffffffffffff811661079e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324f75747075744f7261636c653a206e65772070726f706f7365722063616e60448201527f6e6f7420626520746865207a65726f206164647265737300000000000000000060648201526084016104f7565b60335473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610871576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4c324f75747075744f7261636c653a2070726f706f7365722063616e6e6f742060448201527f6265207468652073616d6520617320746865206f776e6572000000000000000060648201526084016104f7565b60655460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f3d7728dc2838bb794606bd89f5a37930830b32060f69ee929bbfc59b669024dd90600090a3606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600054610100900460ff161580801561091f5750600054600160ff909116105b806109395750303b158015610939575060005460ff166001145b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f7565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a2357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ade576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4c324f75747075744f7261636c653a2070726f706f7365722063616e6e6f742060448201527f6265207468652073616d6520617320746865206f776e6572000000000000000060648201526084016104f7565b6040805180820182528581524260208083019182527f0000000000000000000000000000000000000000000000000000000000000000600081815260679092529390209151825551600190910155606655610b3761163f565b610b40836106f3565b610b49826115c8565b8015610bac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b60655473ffffffffffffffffffffffffffffffffffffffff163314610c59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324f75747075744f7261636c653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642062792070726f706f73657200000000000000000060648201526084016104f7565b610c61611302565b8314610d15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a4016104f7565b42610d1f846111a5565b10610dac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e20746865206675747572650000000000000000000060648201526084016104f7565b83610e39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f206861736800000000000060648201526084016104f7565b8115610ef55781814014610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b6861736820646f6573206e60448201527f6f74206d6174636820746865206861736820617420746865206578706563746560648201527f6420686569676874000000000000000000000000000000000000000000000000608482015260a4016104f7565b6040805180820182528581524260208083018281526000888152606790925284822093518455516001909301929092556066869055915185929187917fc120f5e881491e6e212befa39e36b8f57d5eca31915f2e5d60a420f418caa6df9190a450505050565b60408051808201909152600080825260208201527f0000000000000000000000000000000000000000000000000000000000000000821015611045576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d6265722063616e60448201527f6e6f74206265206c657373207468616e20746865207374617274696e6720626c60648201527f6f636b206e756d6265722e000000000000000000000000000000000000000000608482015260a4016104f7565b60007f00000000000000000000000000000000000000000000000000000000000000006110927f000000000000000000000000000000000000000000000000000000000000000085611a55565b61109c9190611b11565b9050600081156110df576110d0827f0000000000000000000000000000000000000000000000000000000000000000611a55565b6110da9085611b25565b6110e1565b835b60008181526067602090815260409182902082518084019093528054808452600190910154918301919091529192509061119d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a204e6f206f757470757420666f756e642060448201527f666f72207468617420626c6f636b206e756d6265722e0000000000000000000060648201526084016104f7565b949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000082101561127d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605360248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f742062652067726561746572207468616e206f7220657175616c20746f20737460648201527f617274696e6720626c6f636b206e756d62657200000000000000000000000000608482015260a4016104f7565b7f00000000000000000000000000000000000000000000000000000000000000006112c87f000000000000000000000000000000000000000000000000000000000000000084611a55565b6112d29190611b3d565b6112fc907f0000000000000000000000000000000000000000000000000000000000000000611b25565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006066546113329190611b25565b905090565b61133f611412565b60655473ffffffffffffffffffffffffffffffffffffffff908116908216036113ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4c324f75747075744f7261636c653a206f776e65722063616e6e6f742062652060448201527f7468652073616d65206173207468652070726f706f736572000000000000000060648201526084016104f7565b6113f3816116de565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f7565b6060816000036114d657505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561150057806114ea81611b7a565b91506114f99050600a83611bb2565b91506114da565b60008167ffffffffffffffff81111561151b5761151b611832565b6040519080825280601f01601f191660200182016040528015611545576020820181803683370190505b5090505b841561119d5761155a600183611a55565b9150611567600a86611b11565b611572906030611b25565b60f81b81838151811061158757611587611bc6565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506115c1600a86611bb2565b9450611549565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166116d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104f7565b6106f1611792565b6116e6611412565b73ffffffffffffffffffffffffffffffffffffffff8116611789576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104f7565b6113f3816115c8565b600054610100900460ff16611829576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104f7565b6106f1336115c8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006040828403121561187357600080fd5b6040516040810181811067ffffffffffffffff821117156118bd577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823581526020928301359281019290925250919050565b60005b838110156118f25781810151838201526020016118da565b83811115610bac5750506000910152565b60208152600082518060208401526119228160408501602087016118d7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461197857600080fd5b919050565b60006020828403121561198f57600080fd5b61199882611954565b9392505050565b6000806000606084860312156119b457600080fd5b833592506119c460208501611954565b91506119d260408501611954565b90509250925092565b600080600080608085870312156119f157600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215611a1f57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611a6757611a67611a26565b500390565b60008451611a7e8184602089016118d7565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611aba816001850160208a016118d7565b60019201918201528351611ad58160028401602088016118d7565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611b2057611b20611ae2565b500690565b60008219821115611b3857611b38611a26565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611b7557611b75611a26565b500290565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611bab57611bab611a26565b5060010190565b600082611bc157611bc1611ae2565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f7420694c324f75747075744f7261636c653a2070726f706f7365722063616e6e6f7420", } // L2OutputOracleABI is the input ABI used to generate the binding from. @@ -621,25 +621,25 @@ func (_L2OutputOracle *L2OutputOracleTransactorSession) DeleteL2Output(_proposal return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _proposal) } -// Initialize is a paid mutator transaction binding the contract method 0xd20b1a51. +// Initialize is a paid mutator transaction binding the contract method 0x88b117b3. // -// Solidity: function initialize(bytes32 _genesisL2Output, uint256 _startingBlockNumber, address _proposer, address _owner) returns() -func (_L2OutputOracle *L2OutputOracleTransactor) Initialize(opts *bind.TransactOpts, _genesisL2Output [32]byte, _startingBlockNumber *big.Int, _proposer common.Address, _owner common.Address) (*types.Transaction, error) { - return _L2OutputOracle.contract.Transact(opts, "initialize", _genesisL2Output, _startingBlockNumber, _proposer, _owner) +// Solidity: function initialize(bytes32 _genesisL2Output, address _proposer, address _owner) returns() +func (_L2OutputOracle *L2OutputOracleTransactor) Initialize(opts *bind.TransactOpts, _genesisL2Output [32]byte, _proposer common.Address, _owner common.Address) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "initialize", _genesisL2Output, _proposer, _owner) } -// Initialize is a paid mutator transaction binding the contract method 0xd20b1a51. +// Initialize is a paid mutator transaction binding the contract method 0x88b117b3. // -// Solidity: function initialize(bytes32 _genesisL2Output, uint256 _startingBlockNumber, address _proposer, address _owner) returns() -func (_L2OutputOracle *L2OutputOracleSession) Initialize(_genesisL2Output [32]byte, _startingBlockNumber *big.Int, _proposer common.Address, _owner common.Address) (*types.Transaction, error) { - return _L2OutputOracle.Contract.Initialize(&_L2OutputOracle.TransactOpts, _genesisL2Output, _startingBlockNumber, _proposer, _owner) +// Solidity: function initialize(bytes32 _genesisL2Output, address _proposer, address _owner) returns() +func (_L2OutputOracle *L2OutputOracleSession) Initialize(_genesisL2Output [32]byte, _proposer common.Address, _owner common.Address) (*types.Transaction, error) { + return _L2OutputOracle.Contract.Initialize(&_L2OutputOracle.TransactOpts, _genesisL2Output, _proposer, _owner) } -// Initialize is a paid mutator transaction binding the contract method 0xd20b1a51. +// Initialize is a paid mutator transaction binding the contract method 0x88b117b3. // -// Solidity: function initialize(bytes32 _genesisL2Output, uint256 _startingBlockNumber, address _proposer, address _owner) returns() -func (_L2OutputOracle *L2OutputOracleTransactorSession) Initialize(_genesisL2Output [32]byte, _startingBlockNumber *big.Int, _proposer common.Address, _owner common.Address) (*types.Transaction, error) { - return _L2OutputOracle.Contract.Initialize(&_L2OutputOracle.TransactOpts, _genesisL2Output, _startingBlockNumber, _proposer, _owner) +// Solidity: function initialize(bytes32 _genesisL2Output, address _proposer, address _owner) returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) Initialize(_genesisL2Output [32]byte, _proposer common.Address, _owner common.Address) (*types.Transaction, error) { + return _L2OutputOracle.Contract.Initialize(&_L2OutputOracle.TransactOpts, _genesisL2Output, _proposer, _owner) } // ProposeL2Output is a paid mutator transaction binding the contract method 0x9aaab648. diff --git a/op-bindings/bindings/l2standardbridge_more.go b/op-bindings/bindings/l2standardbridge_more.go index 1b7553e2dbe86..1dbd56115bb4e 100644 --- a/op-bindings/bindings/l2standardbridge_more.go +++ b/op-bindings/bindings/l2standardbridge_more.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const L2StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":26285,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":26288,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer_1_0_20\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_address\"},{\"astId\":26295,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":26300,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_array(t_uint256)47_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)47_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[47]\",\"numberOfBytes\":\"1504\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" +const L2StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":26373,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":26376,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer_1_0_20\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_address\"},{\"astId\":26383,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":26388,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_array(t_uint256)47_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)47_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[47]\",\"numberOfBytes\":\"1504\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" var L2StandardBridgeStorageLayout = new(solc.StorageLayout) diff --git a/op-bindings/bindings/l2tol1messagepasser.go b/op-bindings/bindings/l2tol1messagepasser.go index fcbd08d2ecd5d..241c88b9356f8 100644 --- a/op-bindings/bindings/l2tol1messagepasser.go +++ b/op-bindings/bindings/l2tol1messagepasser.go @@ -30,8 +30,8 @@ var ( // L2ToL1MessagePasserMetaData contains all meta data concerning the L2ToL1MessagePasser contract. var L2ToL1MessagePasserMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"WithdrawalInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalInitiatedExtension1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrawerBalanceBurnt\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"initiateWithdrawal\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"sentMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60e060405234801561001057600080fd5b506000608081905260a052600160c05260805160a05160c05161091361004f60003960006102fe015260006102d5015260006102ac01526109136000f3fe60806040526004361061005e5760003560e01c806382e3702d1161004357806382e3702d146100c7578063affed0e014610107578063c2b3e5ac1461012b57600080fd5b806344df8e701461008757806354fd4d501461009c57600080fd5b366100825761008033620186a060405180602001604052806000815250610139565b005b600080fd5b34801561009357600080fd5b5061008061026d565b3480156100a857600080fd5b506100b16102a5565b6040516100be9190610587565b60405180910390f35b3480156100d357600080fd5b506100f76100e23660046105a1565b60006020819052908152604090205460ff1681565b60405190151581526020016100be565b34801561011357600080fd5b5061011d60015481565b6040519081526020016100be565b6100806101393660046105e9565b600061019e6040518060c0016040528060015481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200134815260200185815260200184815250610348565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a61369061022c903490899089906106ed565b60405180910390a460405181907f2ef6ceb1668fdd882b1f89ddd53a666b0c1113d14cf90c0fbf97c7b1ad880fbb90600090a2505060018054810190555050565b4761027781610395565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60606102d07f00000000000000000000000000000000000000000000000000000000000000006103c4565b6102f97f00000000000000000000000000000000000000000000000000000000000000006103c4565b6103227f00000000000000000000000000000000000000000000000000000000000000006103c4565b60405160200161033493929190610715565b604051602081830303815290604052905090565b80516020808301516040808501516060860151608087015160a0880151935160009761037897909695910161078b565b604051602081830303815290604052805190602001209050919050565b806040516103a290610501565b6040518091039082f09050801580156103bf573d6000803e3d6000fd5b505050565b60608160000361040757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610431578061041b81610811565b915061042a9050600a83610878565b915061040b565b60008167ffffffffffffffff81111561044c5761044c6105ba565b6040519080825280601f01601f191660200182016040528015610476576020820181803683370190505b5090505b84156104f95761048b60018361088c565b9150610498600a866108a3565b6104a39060306108b7565b60f81b8183815181106104b8576104b86108cf565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104f2600a86610878565b945061047a565b949350505050565b6008806108ff83390190565b60005b83811015610528578181015183820152602001610510565b83811115610537576000848401525b50505050565b6000815180845261055581602086016020860161050d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061059a602083018461053d565b9392505050565b6000602082840312156105b357600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156105fe57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff8116811461062257600080fd5b925060208401359150604084013567ffffffffffffffff8082111561064657600080fd5b818601915086601f83011261065a57600080fd5b81358181111561066c5761066c6105ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156106b2576106b26105ba565b816040528281528960208487010111156106cb57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b83815282602082015260606040820152600061070c606083018461053d565b95945050505050565b6000845161072781846020890161050d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610763816001850160208a0161050d565b6001920191820152835161077e81600284016020880161050d565b0160020195945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526107d660c083018461053d565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610842576108426107e2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261088757610887610849565b500490565b60008282101561089e5761089e6107e2565b500390565b6000826108b2576108b2610849565b500690565b600082198211156108ca576108ca6107e2565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405230fffea164736f6c634300080f000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"MessagePassed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"MessagePassedExtension1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrawerBalanceBurnt\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"initiateWithdrawal\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"sentMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x60e060405234801561001057600080fd5b506000608081905260a052600160c05260805160a05160c05161091361004f60003960006102fe015260006102d5015260006102ac01526109136000f3fe60806040526004361061005e5760003560e01c806382e3702d1161004357806382e3702d146100c7578063affed0e014610107578063c2b3e5ac1461012b57600080fd5b806344df8e701461008757806354fd4d501461009c57600080fd5b366100825761008033620186a060405180602001604052806000815250610139565b005b600080fd5b34801561009357600080fd5b5061008061026d565b3480156100a857600080fd5b506100b16102a5565b6040516100be9190610587565b60405180910390f35b3480156100d357600080fd5b506100f76100e23660046105a1565b60006020819052908152604090205460ff1681565b60405190151581526020016100be565b34801561011357600080fd5b5061011d60015481565b6040519081526020016100be565b6100806101393660046105e9565b600061019e6040518060c0016040528060015481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200134815260200185815260200184815250610348565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f7744840cae4793a72467311120512aa98e4398bcd2b9d379b2b9c3b60fa03d729061022c903490899089906106ed565b60405180910390a460405181907fedd348f9c36ef1a5b0747bb5039752707059f0b934c8e508b3271e08fbd0122c90600090a2505060018054810190555050565b4761027781610395565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60606102d07f00000000000000000000000000000000000000000000000000000000000000006103c4565b6102f97f00000000000000000000000000000000000000000000000000000000000000006103c4565b6103227f00000000000000000000000000000000000000000000000000000000000000006103c4565b60405160200161033493929190610715565b604051602081830303815290604052905090565b80516020808301516040808501516060860151608087015160a0880151935160009761037897909695910161078b565b604051602081830303815290604052805190602001209050919050565b806040516103a290610501565b6040518091039082f09050801580156103bf573d6000803e3d6000fd5b505050565b60608160000361040757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610431578061041b81610811565b915061042a9050600a83610878565b915061040b565b60008167ffffffffffffffff81111561044c5761044c6105ba565b6040519080825280601f01601f191660200182016040528015610476576020820181803683370190505b5090505b84156104f95761048b60018361088c565b9150610498600a866108a3565b6104a39060306108b7565b60f81b8183815181106104b8576104b86108cf565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104f2600a86610878565b945061047a565b949350505050565b6008806108ff83390190565b60005b83811015610528578181015183820152602001610510565b83811115610537576000848401525b50505050565b6000815180845261055581602086016020860161050d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061059a602083018461053d565b9392505050565b6000602082840312156105b357600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156105fe57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff8116811461062257600080fd5b925060208401359150604084013567ffffffffffffffff8082111561064657600080fd5b818601915086601f83011261065a57600080fd5b81358181111561066c5761066c6105ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156106b2576106b26105ba565b816040528281528960208487010111156106cb57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b83815282602082015260606040820152600061070c606083018461053d565b95945050505050565b6000845161072781846020890161050d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610763816001850160208a0161050d565b6001920191820152835161077e81600284016020880161050d565b0160020195945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526107d660c083018461053d565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610842576108426107e2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261088757610887610849565b500490565b60008282101561089e5761089e6107e2565b500390565b6000826108b2576108b2610849565b500690565b600082198211156108ca576108ca6107e2565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405230fffea164736f6c634300080f000a", } // L2ToL1MessagePasserABI is the input ABI used to generate the binding from. @@ -357,9 +357,9 @@ func (_L2ToL1MessagePasser *L2ToL1MessagePasserTransactorSession) Receive() (*ty return _L2ToL1MessagePasser.Contract.Receive(&_L2ToL1MessagePasser.TransactOpts) } -// L2ToL1MessagePasserWithdrawalInitiatedIterator is returned from FilterWithdrawalInitiated and is used to iterate over the raw logs and unpacked data for WithdrawalInitiated events raised by the L2ToL1MessagePasser contract. -type L2ToL1MessagePasserWithdrawalInitiatedIterator struct { - Event *L2ToL1MessagePasserWithdrawalInitiated // Event containing the contract specifics and raw log +// L2ToL1MessagePasserMessagePassedIterator is returned from FilterMessagePassed and is used to iterate over the raw logs and unpacked data for MessagePassed events raised by the L2ToL1MessagePasser contract. +type L2ToL1MessagePasserMessagePassedIterator struct { + Event *L2ToL1MessagePasserMessagePassed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -373,7 +373,7 @@ type L2ToL1MessagePasserWithdrawalInitiatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *L2ToL1MessagePasserWithdrawalInitiatedIterator) Next() bool { +func (it *L2ToL1MessagePasserMessagePassedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -382,7 +382,7 @@ func (it *L2ToL1MessagePasserWithdrawalInitiatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(L2ToL1MessagePasserWithdrawalInitiated) + it.Event = new(L2ToL1MessagePasserMessagePassed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -397,7 +397,7 @@ func (it *L2ToL1MessagePasserWithdrawalInitiatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(L2ToL1MessagePasserWithdrawalInitiated) + it.Event = new(L2ToL1MessagePasserMessagePassed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -413,19 +413,19 @@ func (it *L2ToL1MessagePasserWithdrawalInitiatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *L2ToL1MessagePasserWithdrawalInitiatedIterator) Error() error { +func (it *L2ToL1MessagePasserMessagePassedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *L2ToL1MessagePasserWithdrawalInitiatedIterator) Close() error { +func (it *L2ToL1MessagePasserMessagePassedIterator) Close() error { it.sub.Unsubscribe() return nil } -// L2ToL1MessagePasserWithdrawalInitiated represents a WithdrawalInitiated event raised by the L2ToL1MessagePasser contract. -type L2ToL1MessagePasserWithdrawalInitiated struct { +// L2ToL1MessagePasserMessagePassed represents a MessagePassed event raised by the L2ToL1MessagePasser contract. +type L2ToL1MessagePasserMessagePassed struct { Nonce *big.Int Sender common.Address Target common.Address @@ -435,10 +435,10 @@ type L2ToL1MessagePasserWithdrawalInitiated struct { Raw types.Log // Blockchain specific contextual infos } -// FilterWithdrawalInitiated is a free log retrieval operation binding the contract event 0x87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136. +// FilterMessagePassed is a free log retrieval operation binding the contract event 0x7744840cae4793a72467311120512aa98e4398bcd2b9d379b2b9c3b60fa03d72. // -// Solidity: event WithdrawalInitiated(uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, uint256 gasLimit, bytes data) -func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) FilterWithdrawalInitiated(opts *bind.FilterOpts, nonce []*big.Int, sender []common.Address, target []common.Address) (*L2ToL1MessagePasserWithdrawalInitiatedIterator, error) { +// Solidity: event MessagePassed(uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, uint256 gasLimit, bytes data) +func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) FilterMessagePassed(opts *bind.FilterOpts, nonce []*big.Int, sender []common.Address, target []common.Address) (*L2ToL1MessagePasserMessagePassedIterator, error) { var nonceRule []interface{} for _, nonceItem := range nonce { @@ -453,17 +453,17 @@ func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) FilterWithdrawalInitiat targetRule = append(targetRule, targetItem) } - logs, sub, err := _L2ToL1MessagePasser.contract.FilterLogs(opts, "WithdrawalInitiated", nonceRule, senderRule, targetRule) + logs, sub, err := _L2ToL1MessagePasser.contract.FilterLogs(opts, "MessagePassed", nonceRule, senderRule, targetRule) if err != nil { return nil, err } - return &L2ToL1MessagePasserWithdrawalInitiatedIterator{contract: _L2ToL1MessagePasser.contract, event: "WithdrawalInitiated", logs: logs, sub: sub}, nil + return &L2ToL1MessagePasserMessagePassedIterator{contract: _L2ToL1MessagePasser.contract, event: "MessagePassed", logs: logs, sub: sub}, nil } -// WatchWithdrawalInitiated is a free log subscription operation binding the contract event 0x87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136. +// WatchMessagePassed is a free log subscription operation binding the contract event 0x7744840cae4793a72467311120512aa98e4398bcd2b9d379b2b9c3b60fa03d72. // -// Solidity: event WithdrawalInitiated(uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, uint256 gasLimit, bytes data) -func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) WatchWithdrawalInitiated(opts *bind.WatchOpts, sink chan<- *L2ToL1MessagePasserWithdrawalInitiated, nonce []*big.Int, sender []common.Address, target []common.Address) (event.Subscription, error) { +// Solidity: event MessagePassed(uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, uint256 gasLimit, bytes data) +func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) WatchMessagePassed(opts *bind.WatchOpts, sink chan<- *L2ToL1MessagePasserMessagePassed, nonce []*big.Int, sender []common.Address, target []common.Address) (event.Subscription, error) { var nonceRule []interface{} for _, nonceItem := range nonce { @@ -478,7 +478,7 @@ func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) WatchWithdrawalInitiate targetRule = append(targetRule, targetItem) } - logs, sub, err := _L2ToL1MessagePasser.contract.WatchLogs(opts, "WithdrawalInitiated", nonceRule, senderRule, targetRule) + logs, sub, err := _L2ToL1MessagePasser.contract.WatchLogs(opts, "MessagePassed", nonceRule, senderRule, targetRule) if err != nil { return nil, err } @@ -488,8 +488,8 @@ func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) WatchWithdrawalInitiate select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(L2ToL1MessagePasserWithdrawalInitiated) - if err := _L2ToL1MessagePasser.contract.UnpackLog(event, "WithdrawalInitiated", log); err != nil { + event := new(L2ToL1MessagePasserMessagePassed) + if err := _L2ToL1MessagePasser.contract.UnpackLog(event, "MessagePassed", log); err != nil { return err } event.Raw = log @@ -510,21 +510,21 @@ func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) WatchWithdrawalInitiate }), nil } -// ParseWithdrawalInitiated is a log parse operation binding the contract event 0x87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136. +// ParseMessagePassed is a log parse operation binding the contract event 0x7744840cae4793a72467311120512aa98e4398bcd2b9d379b2b9c3b60fa03d72. // -// Solidity: event WithdrawalInitiated(uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, uint256 gasLimit, bytes data) -func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) ParseWithdrawalInitiated(log types.Log) (*L2ToL1MessagePasserWithdrawalInitiated, error) { - event := new(L2ToL1MessagePasserWithdrawalInitiated) - if err := _L2ToL1MessagePasser.contract.UnpackLog(event, "WithdrawalInitiated", log); err != nil { +// Solidity: event MessagePassed(uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, uint256 gasLimit, bytes data) +func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) ParseMessagePassed(log types.Log) (*L2ToL1MessagePasserMessagePassed, error) { + event := new(L2ToL1MessagePasserMessagePassed) + if err := _L2ToL1MessagePasser.contract.UnpackLog(event, "MessagePassed", log); err != nil { return nil, err } event.Raw = log return event, nil } -// L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator is returned from FilterWithdrawalInitiatedExtension1 and is used to iterate over the raw logs and unpacked data for WithdrawalInitiatedExtension1 events raised by the L2ToL1MessagePasser contract. -type L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator struct { - Event *L2ToL1MessagePasserWithdrawalInitiatedExtension1 // Event containing the contract specifics and raw log +// L2ToL1MessagePasserMessagePassedExtension1Iterator is returned from FilterMessagePassedExtension1 and is used to iterate over the raw logs and unpacked data for MessagePassedExtension1 events raised by the L2ToL1MessagePasser contract. +type L2ToL1MessagePasserMessagePassedExtension1Iterator struct { + Event *L2ToL1MessagePasserMessagePassedExtension1 // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -538,7 +538,7 @@ type L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator) Next() bool { +func (it *L2ToL1MessagePasserMessagePassedExtension1Iterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -547,7 +547,7 @@ func (it *L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator) Next() bool if it.done { select { case log := <-it.logs: - it.Event = new(L2ToL1MessagePasserWithdrawalInitiatedExtension1) + it.Event = new(L2ToL1MessagePasserMessagePassedExtension1) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -562,7 +562,7 @@ func (it *L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator) Next() bool // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(L2ToL1MessagePasserWithdrawalInitiatedExtension1) + it.Event = new(L2ToL1MessagePasserMessagePassedExtension1) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -578,51 +578,51 @@ func (it *L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator) Next() bool } // Error returns any retrieval or parsing error occurred during filtering. -func (it *L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator) Error() error { +func (it *L2ToL1MessagePasserMessagePassedExtension1Iterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator) Close() error { +func (it *L2ToL1MessagePasserMessagePassedExtension1Iterator) Close() error { it.sub.Unsubscribe() return nil } -// L2ToL1MessagePasserWithdrawalInitiatedExtension1 represents a WithdrawalInitiatedExtension1 event raised by the L2ToL1MessagePasser contract. -type L2ToL1MessagePasserWithdrawalInitiatedExtension1 struct { +// L2ToL1MessagePasserMessagePassedExtension1 represents a MessagePassedExtension1 event raised by the L2ToL1MessagePasser contract. +type L2ToL1MessagePasserMessagePassedExtension1 struct { Hash [32]byte Raw types.Log // Blockchain specific contextual infos } -// FilterWithdrawalInitiatedExtension1 is a free log retrieval operation binding the contract event 0x2ef6ceb1668fdd882b1f89ddd53a666b0c1113d14cf90c0fbf97c7b1ad880fbb. +// FilterMessagePassedExtension1 is a free log retrieval operation binding the contract event 0xedd348f9c36ef1a5b0747bb5039752707059f0b934c8e508b3271e08fbd0122c. // -// Solidity: event WithdrawalInitiatedExtension1(bytes32 indexed hash) -func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) FilterWithdrawalInitiatedExtension1(opts *bind.FilterOpts, hash [][32]byte) (*L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator, error) { +// Solidity: event MessagePassedExtension1(bytes32 indexed hash) +func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) FilterMessagePassedExtension1(opts *bind.FilterOpts, hash [][32]byte) (*L2ToL1MessagePasserMessagePassedExtension1Iterator, error) { var hashRule []interface{} for _, hashItem := range hash { hashRule = append(hashRule, hashItem) } - logs, sub, err := _L2ToL1MessagePasser.contract.FilterLogs(opts, "WithdrawalInitiatedExtension1", hashRule) + logs, sub, err := _L2ToL1MessagePasser.contract.FilterLogs(opts, "MessagePassedExtension1", hashRule) if err != nil { return nil, err } - return &L2ToL1MessagePasserWithdrawalInitiatedExtension1Iterator{contract: _L2ToL1MessagePasser.contract, event: "WithdrawalInitiatedExtension1", logs: logs, sub: sub}, nil + return &L2ToL1MessagePasserMessagePassedExtension1Iterator{contract: _L2ToL1MessagePasser.contract, event: "MessagePassedExtension1", logs: logs, sub: sub}, nil } -// WatchWithdrawalInitiatedExtension1 is a free log subscription operation binding the contract event 0x2ef6ceb1668fdd882b1f89ddd53a666b0c1113d14cf90c0fbf97c7b1ad880fbb. +// WatchMessagePassedExtension1 is a free log subscription operation binding the contract event 0xedd348f9c36ef1a5b0747bb5039752707059f0b934c8e508b3271e08fbd0122c. // -// Solidity: event WithdrawalInitiatedExtension1(bytes32 indexed hash) -func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) WatchWithdrawalInitiatedExtension1(opts *bind.WatchOpts, sink chan<- *L2ToL1MessagePasserWithdrawalInitiatedExtension1, hash [][32]byte) (event.Subscription, error) { +// Solidity: event MessagePassedExtension1(bytes32 indexed hash) +func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) WatchMessagePassedExtension1(opts *bind.WatchOpts, sink chan<- *L2ToL1MessagePasserMessagePassedExtension1, hash [][32]byte) (event.Subscription, error) { var hashRule []interface{} for _, hashItem := range hash { hashRule = append(hashRule, hashItem) } - logs, sub, err := _L2ToL1MessagePasser.contract.WatchLogs(opts, "WithdrawalInitiatedExtension1", hashRule) + logs, sub, err := _L2ToL1MessagePasser.contract.WatchLogs(opts, "MessagePassedExtension1", hashRule) if err != nil { return nil, err } @@ -632,8 +632,8 @@ func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) WatchWithdrawalInitiate select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(L2ToL1MessagePasserWithdrawalInitiatedExtension1) - if err := _L2ToL1MessagePasser.contract.UnpackLog(event, "WithdrawalInitiatedExtension1", log); err != nil { + event := new(L2ToL1MessagePasserMessagePassedExtension1) + if err := _L2ToL1MessagePasser.contract.UnpackLog(event, "MessagePassedExtension1", log); err != nil { return err } event.Raw = log @@ -654,12 +654,12 @@ func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) WatchWithdrawalInitiate }), nil } -// ParseWithdrawalInitiatedExtension1 is a log parse operation binding the contract event 0x2ef6ceb1668fdd882b1f89ddd53a666b0c1113d14cf90c0fbf97c7b1ad880fbb. +// ParseMessagePassedExtension1 is a log parse operation binding the contract event 0xedd348f9c36ef1a5b0747bb5039752707059f0b934c8e508b3271e08fbd0122c. // -// Solidity: event WithdrawalInitiatedExtension1(bytes32 indexed hash) -func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) ParseWithdrawalInitiatedExtension1(log types.Log) (*L2ToL1MessagePasserWithdrawalInitiatedExtension1, error) { - event := new(L2ToL1MessagePasserWithdrawalInitiatedExtension1) - if err := _L2ToL1MessagePasser.contract.UnpackLog(event, "WithdrawalInitiatedExtension1", log); err != nil { +// Solidity: event MessagePassedExtension1(bytes32 indexed hash) +func (_L2ToL1MessagePasser *L2ToL1MessagePasserFilterer) ParseMessagePassedExtension1(log types.Log) (*L2ToL1MessagePasserMessagePassedExtension1, error) { + event := new(L2ToL1MessagePasserMessagePassedExtension1) + if err := _L2ToL1MessagePasser.contract.UnpackLog(event, "MessagePassedExtension1", log); err != nil { return nil, err } event.Raw = log diff --git a/op-bindings/bindings/l2tol1messagepasser_more.go b/op-bindings/bindings/l2tol1messagepasser_more.go index fb28bfbbd25cd..ebeedcbe1c815 100644 --- a/op-bindings/bindings/l2tol1messagepasser_more.go +++ b/op-bindings/bindings/l2tol1messagepasser_more.go @@ -9,11 +9,11 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const L2ToL1MessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":2546,\"contract\":\"contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser\",\"label\":\"sentMessages\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":2549,\"contract\":\"contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser\",\"label\":\"nonce\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" +const L2ToL1MessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":2543,\"contract\":\"contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser\",\"label\":\"sentMessages\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":2546,\"contract\":\"contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser\",\"label\":\"nonce\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" var L2ToL1MessagePasserStorageLayout = new(solc.StorageLayout) -var L2ToL1MessagePasserDeployedBin = "0x60806040526004361061005e5760003560e01c806382e3702d1161004357806382e3702d146100c7578063affed0e014610107578063c2b3e5ac1461012b57600080fd5b806344df8e701461008757806354fd4d501461009c57600080fd5b366100825761008033620186a060405180602001604052806000815250610139565b005b600080fd5b34801561009357600080fd5b5061008061026d565b3480156100a857600080fd5b506100b16102a5565b6040516100be9190610587565b60405180910390f35b3480156100d357600080fd5b506100f76100e23660046105a1565b60006020819052908152604090205460ff1681565b60405190151581526020016100be565b34801561011357600080fd5b5061011d60015481565b6040519081526020016100be565b6100806101393660046105e9565b600061019e6040518060c0016040528060015481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200134815260200185815260200184815250610348565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a61369061022c903490899089906106ed565b60405180910390a460405181907f2ef6ceb1668fdd882b1f89ddd53a666b0c1113d14cf90c0fbf97c7b1ad880fbb90600090a2505060018054810190555050565b4761027781610395565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60606102d07f00000000000000000000000000000000000000000000000000000000000000006103c4565b6102f97f00000000000000000000000000000000000000000000000000000000000000006103c4565b6103227f00000000000000000000000000000000000000000000000000000000000000006103c4565b60405160200161033493929190610715565b604051602081830303815290604052905090565b80516020808301516040808501516060860151608087015160a0880151935160009761037897909695910161078b565b604051602081830303815290604052805190602001209050919050565b806040516103a290610501565b6040518091039082f09050801580156103bf573d6000803e3d6000fd5b505050565b60608160000361040757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610431578061041b81610811565b915061042a9050600a83610878565b915061040b565b60008167ffffffffffffffff81111561044c5761044c6105ba565b6040519080825280601f01601f191660200182016040528015610476576020820181803683370190505b5090505b84156104f95761048b60018361088c565b9150610498600a866108a3565b6104a39060306108b7565b60f81b8183815181106104b8576104b86108cf565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104f2600a86610878565b945061047a565b949350505050565b6008806108ff83390190565b60005b83811015610528578181015183820152602001610510565b83811115610537576000848401525b50505050565b6000815180845261055581602086016020860161050d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061059a602083018461053d565b9392505050565b6000602082840312156105b357600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156105fe57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff8116811461062257600080fd5b925060208401359150604084013567ffffffffffffffff8082111561064657600080fd5b818601915086601f83011261065a57600080fd5b81358181111561066c5761066c6105ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156106b2576106b26105ba565b816040528281528960208487010111156106cb57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b83815282602082015260606040820152600061070c606083018461053d565b95945050505050565b6000845161072781846020890161050d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610763816001850160208a0161050d565b6001920191820152835161077e81600284016020880161050d565b0160020195945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526107d660c083018461053d565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610842576108426107e2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261088757610887610849565b500490565b60008282101561089e5761089e6107e2565b500390565b6000826108b2576108b2610849565b500690565b600082198211156108ca576108ca6107e2565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405230fffea164736f6c634300080f000a" +var L2ToL1MessagePasserDeployedBin = "0x60806040526004361061005e5760003560e01c806382e3702d1161004357806382e3702d146100c7578063affed0e014610107578063c2b3e5ac1461012b57600080fd5b806344df8e701461008757806354fd4d501461009c57600080fd5b366100825761008033620186a060405180602001604052806000815250610139565b005b600080fd5b34801561009357600080fd5b5061008061026d565b3480156100a857600080fd5b506100b16102a5565b6040516100be9190610587565b60405180910390f35b3480156100d357600080fd5b506100f76100e23660046105a1565b60006020819052908152604090205460ff1681565b60405190151581526020016100be565b34801561011357600080fd5b5061011d60015481565b6040519081526020016100be565b6100806101393660046105e9565b600061019e6040518060c0016040528060015481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200134815260200185815260200184815250610348565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f7744840cae4793a72467311120512aa98e4398bcd2b9d379b2b9c3b60fa03d729061022c903490899089906106ed565b60405180910390a460405181907fedd348f9c36ef1a5b0747bb5039752707059f0b934c8e508b3271e08fbd0122c90600090a2505060018054810190555050565b4761027781610395565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60606102d07f00000000000000000000000000000000000000000000000000000000000000006103c4565b6102f97f00000000000000000000000000000000000000000000000000000000000000006103c4565b6103227f00000000000000000000000000000000000000000000000000000000000000006103c4565b60405160200161033493929190610715565b604051602081830303815290604052905090565b80516020808301516040808501516060860151608087015160a0880151935160009761037897909695910161078b565b604051602081830303815290604052805190602001209050919050565b806040516103a290610501565b6040518091039082f09050801580156103bf573d6000803e3d6000fd5b505050565b60608160000361040757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610431578061041b81610811565b915061042a9050600a83610878565b915061040b565b60008167ffffffffffffffff81111561044c5761044c6105ba565b6040519080825280601f01601f191660200182016040528015610476576020820181803683370190505b5090505b84156104f95761048b60018361088c565b9150610498600a866108a3565b6104a39060306108b7565b60f81b8183815181106104b8576104b86108cf565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104f2600a86610878565b945061047a565b949350505050565b6008806108ff83390190565b60005b83811015610528578181015183820152602001610510565b83811115610537576000848401525b50505050565b6000815180845261055581602086016020860161050d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061059a602083018461053d565b9392505050565b6000602082840312156105b357600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156105fe57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff8116811461062257600080fd5b925060208401359150604084013567ffffffffffffffff8082111561064657600080fd5b818601915086601f83011261065a57600080fd5b81358181111561066c5761066c6105ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156106b2576106b26105ba565b816040528281528960208487010111156106cb57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b83815282602082015260606040820152600061070c606083018461053d565b95945050505050565b6000845161072781846020890161050d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610763816001850160208a0161050d565b6001920191820152835161077e81600284016020880161050d565b0160020195945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526107d660c083018461053d565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610842576108426107e2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261088757610887610849565b500490565b60008282101561089e5761089e6107e2565b500390565b6000826108b2576108b2610849565b500690565b600082198211156108ca576108ca6107e2565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405230fffea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(L2ToL1MessagePasserStorageLayoutJSON), L2ToL1MessagePasserStorageLayout); err != nil { diff --git a/op-bindings/bindings/legacyerc20eth_more.go b/op-bindings/bindings/legacyerc20eth_more.go index 74cc32f68681d..865075dd27572 100644 --- a/op-bindings/bindings/legacyerc20eth_more.go +++ b/op-bindings/bindings/legacyerc20eth_more.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const LegacyERC20ETHStorageLayoutJSON = "{\"storage\":[{\"astId\":27934,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":27940,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":27942,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":27944,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":27946,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":25198,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"remoteToken\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_address\"},{\"astId\":25201,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"bridge\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" +const LegacyERC20ETHStorageLayoutJSON = "{\"storage\":[{\"astId\":28173,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":28179,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":28181,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":28183,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":28185,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":25286,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"remoteToken\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_address\"},{\"astId\":25289,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"bridge\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" var LegacyERC20ETHStorageLayout = new(solc.StorageLayout) diff --git a/op-bindings/bindings/legacymessagepasser_more.go b/op-bindings/bindings/legacymessagepasser_more.go index b912b09f88130..c8f459ef19091 100644 --- a/op-bindings/bindings/legacymessagepasser_more.go +++ b/op-bindings/bindings/legacymessagepasser_more.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const LegacyMessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":3496,\"contract\":\"contracts/legacy/LegacyMessagePasser.sol:LegacyMessagePasser\",\"label\":\"sentMessages\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_bool)\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"}}}" +const LegacyMessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":3493,\"contract\":\"contracts/legacy/LegacyMessagePasser.sol:LegacyMessagePasser\",\"label\":\"sentMessages\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_bool)\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"}}}" var LegacyMessagePasserStorageLayout = new(solc.StorageLayout) diff --git a/op-bindings/bindings/optimismportal.go b/op-bindings/bindings/optimismportal.go index 9b9ee8867cf50..e986a4823daa3 100644 --- a/op-bindings/bindings/optimismportal.go +++ b/op-bindings/bindings/optimismportal.go @@ -49,7 +49,7 @@ type TypesWithdrawalTransaction struct { // OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. var OptimismPortalMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE_FEE_MAX_CHANGE_DENOMINATOR\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ELASTICITY_MULTIPLIER\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_BASE_FEE\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINIMUM_BASE_FEE\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TARGET_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"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\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"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\":\"structTypes.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"isBlockFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162003fab38038062003fab833981016040819052620000359162000261565b6000608081905260a052600160c0526001600160a01b0382166101005260e08190526200006162000069565b50506200029d565b600054610100900460ff16158080156200008a5750600054600160ff909116105b80620000ba5750620000a730620001af60201b620012881760201c565b158015620000ba575060005460ff166001145b620001235760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000147576000805461ff0019166101001790555b603380546001600160a01b03191661dead17905562000165620001be565b8015620001ac576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054610100900460ff166200022b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200011a565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b600080604083850312156200027557600080fd5b82516001600160a01b03811681146200028d57600080fd5b6020939093015192949293505050565b60805160a05160c05160e05161010051613cb4620002f76000396000818161013401528181610b760152610d9d0152600081816103bd015261156101526000610925015260006108fc015260006108d30152613cb46000f3fe6080604052600436106100f65760003560e01c8063a14238e71161008a578063cff0ab9611610059578063cff0ab96146102f7578063e9e05c4214610398578063f4daa291146103ab578063fdc9fe1d146103df57600080fd5b8063a14238e71461026d578063c4fc4798146102ad578063ca3e99ba146102cd578063cd7c9789146102e257600080fd5b80636bb0291e116100c65780636bb0291e146102005780638129fc1c14610215578063867ead131461022a5780639bf62d821461024057600080fd5b80621c2ff61461012257806313620abd1461018057806354fd4d50146101b957806364b79208146101db57600080fd5b3661011d5761011b3334620186a06000604051806020016040528060008152506103ff565b005b600080fd5b34801561012e57600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018c57600080fd5b50610198633b9aca0081565b6040516fffffffffffffffffffffffffffffffff9091168152602001610177565b3480156101c557600080fd5b506101ce6108cc565b6040516101779190613307565b3480156101e757600080fd5b506101f2627a120081565b604051908152602001610177565b34801561020c57600080fd5b506101f2600481565b34801561022157600080fd5b5061011b61096f565b34801561023657600080fd5b506101f261271081565b34801561024c57600080fd5b506033546101569073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027957600080fd5b5061029d61028836600461331a565b60346020526000908152604090205460ff1681565b6040519015158152602001610177565b3480156102b957600080fd5b5061029d6102c836600461331a565b610b2d565b3480156102d957600080fd5b506101f2610bf2565b3480156102ee57600080fd5b506101f2600881565b34801561030357600080fd5b5060015461035f906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610177565b61011b6103a636600461345f565b6103ff565b3480156103b757600080fd5b506101f27f000000000000000000000000000000000000000000000000000000000000000081565b3480156103eb57600080fd5b5061011b6103fa36600461354d565b610c03565b8260005a905083156104b65773ffffffffffffffffffffffffffffffffffffffff8716156104b657604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b333281146104d7575033731111000000000000000000000000000000001111015b600034888888886040516020016104f2959493929190613641565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516105629190613307565b60405180910390a450506001546000906105a2907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436136d5565b9050801561072b5760006105ba6004627a120061371b565b6001546105e59190700100000000000000000000000000000000900467ffffffffffffffff16613783565b9050600060086105f96004627a120061371b565b6001546106199085906fffffffffffffffffffffffffffffffff166137f7565b610623919061371b565b61062d919061371b565b600154909150600090610679906106639061065b9085906fffffffffffffffffffffffffffffffff166138b3565b6127106112a4565b6fffffffffffffffffffffffffffffffff6112bf565b905060018411156106ec576106e9610663670de0b6b3a76400006106d56106a160088361371b565b6106b390670de0b6b3a7640000613783565b6106be60018a6136d5565b6106d090670de0b6b3a7640000613927565b6112ce565b6106df90856137f7565b61065b919061371b565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805484919060109061075e908490700100000000000000000000000000000000900467ffffffffffffffff16613964565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561083a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016104ad565b600154600090610866906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8616613990565b6fffffffffffffffffffffffffffffffff169050600061088a48633b9aca006112ff565b61089490836139c8565b905060005a6108a390866136d5565b9050808211156108bf576108bf6108ba82846136d5565b61130f565b5050505050505050505050565b60606108f77f000000000000000000000000000000000000000000000000000000000000000061133d565b6109207f000000000000000000000000000000000000000000000000000000000000000061133d565b6109497f000000000000000000000000000000000000000000000000000000000000000061133d565b60405160200161095b939291906139dc565b604051602081830303815290604052905090565b600054610100900460ff161580801561098f5750600054600160ff909116105b806109a95750303b1580156109a9575060005460ff166001145b610a35576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104ad565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a9357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610ac761147a565b8015610b2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa158015610bbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be09190613a52565b9050610beb8161155d565b9392505050565b610c006004627a120061371b565b81565b60335473ffffffffffffffffffffffffffffffffffffffff1661dead14610cac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016104ad565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610d6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016104ad565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1c9190613a52565b9050610e278161155d565b610eb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a65640000000000000000000000000000000000000060648201526084016104ad565b610eca610ec536869003860186613aa1565b611597565b815114610f59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016104ad565b6000610f64876115f3565b9050610fab81866040013586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162392505050565b611037576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016104ad565b60008181526034602052604090205460ff16156110d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016104ad565b600081815260346020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055608087015161111f90614e2090613b07565b5a10156111ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c00000000000000000060648201526084016104ad565b8660200151603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000611211886040015189608001518a606001518b60a001516116ea565b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061127690841515815260200190565b60405180910390a25050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156112b457816112b6565b825b90505b92915050565b60008183126112b457816112b6565b60006112b6670de0b6b3a7640000836112e686611704565b6112f091906137f7565b6112fa919061371b565b611948565b6000818310156112b457816112b6565b6000805a90505b825a61132290836136d5565b10156113385761133182613b1f565b9150611316565b505050565b60608160000361138057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113aa578061139481613b1f565b91506113a39050600a836139c8565b9150611384565b60008167ffffffffffffffff8111156113c5576113c561335c565b6040519080825280601f01601f1916602001820160405280156113ef576020820181803683370190505b5090505b8415611472576114046001836136d5565b9150611411600a86613b57565b61141c906030613b07565b60f81b81838151811061143157611431613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061146b600a866139c8565b94506113f3565b949350505050565b600054610100900460ff16611511576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104ad565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b60007f0000000000000000000000000000000000000000000000000000000000000000826020015161158f9190613b07565b421192915050565b600081600001518260200151836040015184606001516040516020016115d6949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a088015193516000976115d6979096959101613b9a565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506116e19101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611b87565b95945050505050565b600080600080845160208601878a8af19695505050505050565b600080821361176f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104ad565b6000606061177c84611bab565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361197957506000919050565b680755bf798b4a1bf1e582126119eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016104ad565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611b9386611c81565b9050611ba181868686611cb3565b9695505050505050565b6000808211611c16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104ad565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611c9d91815260200190565b6040516020818303038152906040529050919050565b6000806000611cc3878686611cf0565b91509150818015611ce557508051602080830191909120875191880191909120145b979650505050505050565b600060606000611cff85611e0b565b90506000806000611d11848a89611f06565b81519295509093509150158080611d255750815b611db1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2070726f76696465642070726f6f6620697320696e60448201527f76616c696400000000000000000000000000000000000000000000000000000060648201526084016104ad565b600081611dcd5760405180602001604052806000815250611df9565b611df986611ddc6001886136d5565b81518110611dec57611dec613b6b565b602002602001015161248f565b919b919a509098505050505050505050565b60606000611e18836124b9565b90506000815167ffffffffffffffff811115611e3657611e3661335c565b604051908082528060200260200182016040528015611e7b57816020015b6040805180820190915260608082526020820152815260200190600190039081611e545790505b50905060005b8251811015611efe576000611eae848381518110611ea157611ea1613b6b565b60200260200101516124ec565b90506040518060400160405280828152602001611eca836124b9565b815250838381518110611edf57611edf613b6b565b6020026020010181905250508080611ef690613b1f565b915050611e81565b509392505050565b60006060818080611f16876125b3565b90506000869050600080611f3d604051806040016040528060608152602001606081525090565b60005b8c5181101561244b578c8181518110611f5b57611f5b613b6b565b602002602001015191508284611f719190613b07565b9350611f7e600188613b07565b965083600003611fff57815180516020909101208514611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016104ad565b61213b565b8151516020116120a157815180516020909101208514611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016104ad565b815185906120ae90613bf1565b1461213b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016104ad565b61214760106001613b07565b826020015151036121b9578551841461244b57600086858151811061216e5761216e613b6b565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061219957612199613b6b565b602002602001015190506121ac81612736565b9650600194505050612439565b6002826020015151036123b15760006121d18361276c565b90506000816000815181106121e8576121e8613b6b565b016020015160f81c905060006121ff600283613c33565b61220a906002613c55565b9050600061221b848360ff16612790565b905060006122298b8a612790565b9050600061223783836127c6565b905060ff85166002148061224e575060ff85166003145b156122a4578083511480156122635750808251145b1561227557612272818b613b07565b99505b507f8000000000000000000000000000000000000000000000000000000000000000995061244b945050505050565b60ff851615806122b7575060ff85166001145b1561232957825181146122f357507f8000000000000000000000000000000000000000000000000000000000000000995061244b945050505050565b61231a886020015160018151811061230d5761230d613b6b565b6020026020010151612736565b9a509750612439945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016104ad565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016104ad565b8061244381613b1f565b915050611f40565b507f800000000000000000000000000000000000000000000000000000000000000084148661247a8786612790565b909e909d50909b509950505050505050505050565b602081015180516060916112b9916124a9906001906136d5565b81518110611ea157611ea1613b6b565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906112b990612872565b606060008060006124fc85612acb565b91945092509050600081600181111561251757612517613c78565b146125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20696e76616c696420524c502062797465732076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6116e185602001518484612fb6565b60606000825160026125c59190613927565b67ffffffffffffffff8111156125dd576125dd61335c565b6040519080825280601f01601f191660200182016040528015612607576020820181803683370190505b50905060005b835181101561272f57600484828151811061262a5761262a613b6b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c8261265f836002613927565b8151811061266f5761266f613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106126b2576126b2613b6b565b01602001516126c4919060f81c613c33565b60f81b826126d3836002613927565b6126de906001613b07565b815181106126ee576126ee613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061272781613b1f565b91505061260d565b5092915050565b600060606020836000015110156127575761275083613094565b9050612763565b612760836124ec565b90505b610beb81613bf1565b60606112b961278b8360200151600081518110611ea157611ea1613b6b565b6125b3565b6060825182106127af57506040805160208101909152600081526112b9565b6112b683838486516127c191906136d5565b61309f565b6000805b8084511180156127da5750808351115b801561285b57508281815181106127f3576127f3613b6b565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061283257612832613b6b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156112b6578061286a81613b1f565b9150506127ca565b606060008061288084612acb565b9193509091506001905081600181111561289c5761289c613c78565b14612929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f524c505265616465723a20696e76616c696420524c50206c6973742076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816129425790505090506000835b8651811015612ac05760208210612a08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2070726f766964656420524c50206c6973742065786360448201527f65656473206d6178206c697374206c656e67746800000000000000000000000060648201526084016104ad565b600080612a456040518060400160405280858c60000151612a2991906136d5565b8152602001858c60200151612a3e9190613b07565b9052612acb565b509150915060405180604001604052808383612a619190613b07565b8152602001848b60200151612a769190613b07565b815250858581518110612a8b57612a8b613b6b565b6020908102919091010152612aa1600185613b07565b9350612aad8183613b07565b612ab79084613b07565b9250505061296f565b508152949350505050565b600080600080846000015111612b63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20524c50206974656d2063616e6e6f74206265206e7560448201527f6c6c00000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6020840151805160001a607f8111612b88576000600160009450945094505050612faf565b60b78111612c44576000612b9d6080836136d5565b905080876000015111612c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f524c505265616465723a20696e76616c696420524c502073686f72742073747260448201527f696e67000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b60019550935060009250612faf915050565b60bf8111612db3576000612c5960b7836136d5565b905080876000015111612cee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67207374726960448201527f6e67206c656e677468000000000000000000000000000000000000000000000060648201526084016104ad565b600183015160208290036101000a9004612d088183613b07565b885111612d97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67207374726960448201527f6e6700000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b612da2826001613b07565b9650945060009350612faf92505050565b60f78111612e6e576000612dc860c0836136d5565b905080876000015111612e5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f524c505265616465723a20696e76616c696420524c502073686f7274206c697360448201527f740000000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b600195509350849250612faf915050565b6000612e7b60f7836136d5565b905080876000015111612f10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67206c69737460448201527f206c656e6774680000000000000000000000000000000000000000000000000060648201526084016104ad565b600183015160208290036101000a9004612f2a8183613b07565b885111612f93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67206c69737460448201526064016104ad565b612f9e826001613b07565b9650945060019350612faf92505050565b9193909250565b606060008267ffffffffffffffff811115612fd357612fd361335c565b6040519080825280601f01601f191660200182016040528015612ffd576020820181803683370190505b5090508051600003613010579050610beb565b600061301c8587613b07565b90506020820160005b6130306020876139c8565b8110156130675782518252613046602084613b07565b9250613053602083613b07565b91508061305f81613b1f565b915050613025565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606112b982613277565b60608182601f01101561310e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104ad565b82828401101561317a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104ad565b818301845110156131e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016104ad565b606082158015613206576040519150600082526020820160405261326e565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561323f578051835260209283019201613227565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60606112b9826020015160008460000151612fb6565b60005b838110156132a8578181015183820152602001613290565b838111156132b7576000848401525b50505050565b600081518084526132d581602086016020860161328d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112b660208301846132bd565b60006020828403121561332c57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461335757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156133ae576133ae61335c565b60405290565b600082601f8301126133c557600080fd5b813567ffffffffffffffff808211156133e0576133e061335c565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156134265761342661335c565b8160405283815286602085880101111561343f57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a0868803121561347757600080fd5b61348086613333565b945060208601359350604086013567ffffffffffffffff80821682146134a557600080fd5b90935060608701359081151582146134bc57600080fd5b909250608087013590808211156134d257600080fd5b506134df888289016133b4565b9150509295509295909350565b6000608082840312156134fe57600080fd5b50919050565b60008083601f84011261351657600080fd5b50813567ffffffffffffffff81111561352e57600080fd5b60208301915083602082850101111561354657600080fd5b9250929050565b600080600080600060e0868803121561356557600080fd5b853567ffffffffffffffff8082111561357d57600080fd5b9087019060c0828a03121561359157600080fd5b61359961338b565b823581526135a960208401613333565b60208201526135ba60408401613333565b6040820152606083013560608201526080830135608082015260a0830135828111156135e557600080fd5b6135f18b8286016133b4565b60a08301525096506020880135955061360d8960408a016134ec565b945060c088013591508082111561362357600080fd5b5061363088828901613504565b969995985093965092949392505050565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161369581604985016020870161328d565b919091016049019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156136e7576136e76136a6565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261372a5761372a6136ec565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561377e5761377e6136a6565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156137bd576137bd6136a6565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156137f1576137f16136a6565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613838576138386136a6565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615613873576138736136a6565b6000871292508782058712848416161561388f5761388f6136a6565b878505871281841616156138a5576138a56136a6565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156138ed576138ed6136a6565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615613921576139216136a6565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561395f5761395f6136a6565b500290565b600067ffffffffffffffff808316818516808303821115613987576139876136a6565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156139bf576139bf6136a6565b02949350505050565b6000826139d7576139d76136ec565b500490565b600084516139ee81846020890161328d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613a2a816001850160208a0161328d565b60019201918201528351613a4581600284016020880161328d565b0160020195945050505050565b600060408284031215613a6457600080fd5b6040516040810181811067ffffffffffffffff82111715613a8757613a8761335c565b604052825181526020928301519281019290925250919050565b600060808284031215613ab357600080fd5b6040516080810181811067ffffffffffffffff82111715613ad657613ad661335c565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b60008219821115613b1a57613b1a6136a6565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613b5057613b506136a6565b5060010190565b600082613b6657613b666136ec565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152613be560c08301846132bd565b98975050505050505050565b805160208083015191908110156134fe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600060ff831680613c4657613c466136ec565b8060ff84160691505092915050565b600060ff821660ff841680821015613c6f57613c6f6136a6565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", + Bin: "0x6101206040523480156200001257600080fd5b5060405162003fab38038062003fab833981016040819052620000359162000261565b6000608081905260a052600160c0526001600160a01b0382166101005260e08190526200006162000069565b50506200029d565b600054610100900460ff16158080156200008a5750600054600160ff909116105b80620000ba5750620000a730620001af60201b620012881760201c565b158015620000ba575060005460ff166001145b620001235760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000147576000805461ff0019166101001790555b603280546001600160a01b03191661dead17905562000165620001be565b8015620001ac576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054610100900460ff166200022b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200011a565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b600080604083850312156200027557600080fd5b82516001600160a01b03811681146200028d57600080fd5b6020939093015192949293505050565b60805160a05160c05160e05161010051613cb4620002f76000396000818161013401528181610b760152610d9d0152600081816103bd015261156101526000610925015260006108fc015260006108d30152613cb46000f3fe6080604052600436106100f65760003560e01c8063a14238e71161008a578063cff0ab9611610059578063cff0ab96146102f7578063e9e05c4214610398578063f4daa291146103ab578063fdc9fe1d146103df57600080fd5b8063a14238e71461026d578063c4fc4798146102ad578063ca3e99ba146102cd578063cd7c9789146102e257600080fd5b80636bb0291e116100c65780636bb0291e146102005780638129fc1c14610215578063867ead131461022a5780639bf62d821461024057600080fd5b80621c2ff61461012257806313620abd1461018057806354fd4d50146101b957806364b79208146101db57600080fd5b3661011d5761011b3334620186a06000604051806020016040528060008152506103ff565b005b600080fd5b34801561012e57600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018c57600080fd5b50610198633b9aca0081565b6040516fffffffffffffffffffffffffffffffff9091168152602001610177565b3480156101c557600080fd5b506101ce6108cc565b6040516101779190613307565b3480156101e757600080fd5b506101f2627a120081565b604051908152602001610177565b34801561020c57600080fd5b506101f2600481565b34801561022157600080fd5b5061011b61096f565b34801561023657600080fd5b506101f261271081565b34801561024c57600080fd5b506032546101569073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027957600080fd5b5061029d61028836600461331a565b60336020526000908152604090205460ff1681565b6040519015158152602001610177565b3480156102b957600080fd5b5061029d6102c836600461331a565b610b2d565b3480156102d957600080fd5b506101f2610bf2565b3480156102ee57600080fd5b506101f2600881565b34801561030357600080fd5b5060015461035f906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610177565b61011b6103a636600461345f565b6103ff565b3480156103b757600080fd5b506101f27f000000000000000000000000000000000000000000000000000000000000000081565b3480156103eb57600080fd5b5061011b6103fa36600461354d565b610c03565b8260005a905083156104b65773ffffffffffffffffffffffffffffffffffffffff8716156104b657604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b333281146104d7575033731111000000000000000000000000000000001111015b600034888888886040516020016104f2959493929190613641565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516105629190613307565b60405180910390a450506001546000906105a2907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436136d5565b9050801561072b5760006105ba6004627a120061371b565b6001546105e59190700100000000000000000000000000000000900467ffffffffffffffff16613783565b9050600060086105f96004627a120061371b565b6001546106199085906fffffffffffffffffffffffffffffffff166137f7565b610623919061371b565b61062d919061371b565b600154909150600090610679906106639061065b9085906fffffffffffffffffffffffffffffffff166138b3565b6127106112a4565b6fffffffffffffffffffffffffffffffff6112bf565b905060018411156106ec576106e9610663670de0b6b3a76400006106d56106a160088361371b565b6106b390670de0b6b3a7640000613783565b6106be60018a6136d5565b6106d090670de0b6b3a7640000613927565b6112ce565b6106df90856137f7565b61065b919061371b565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805484919060109061075e908490700100000000000000000000000000000000900467ffffffffffffffff16613964565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561083a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016104ad565b600154600090610866906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8616613990565b6fffffffffffffffffffffffffffffffff169050600061088a48633b9aca006112ff565b61089490836139c8565b905060005a6108a390866136d5565b9050808211156108bf576108bf6108ba82846136d5565b61130f565b5050505050505050505050565b60606108f77f000000000000000000000000000000000000000000000000000000000000000061133d565b6109207f000000000000000000000000000000000000000000000000000000000000000061133d565b6109497f000000000000000000000000000000000000000000000000000000000000000061133d565b60405160200161095b939291906139dc565b604051602081830303815290604052905090565b600054610100900460ff161580801561098f5750600054600160ff909116105b806109a95750303b1580156109a9575060005460ff166001145b610a35576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104ad565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a9357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610ac761147a565b8015610b2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa158015610bbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be09190613a52565b9050610beb8161155d565b9392505050565b610c006004627a120061371b565b81565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610cac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016104ad565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610d6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016104ad565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1c9190613a52565b9050610e278161155d565b610eb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a65640000000000000000000000000000000000000060648201526084016104ad565b610eca610ec536869003860186613aa1565b611597565b815114610f59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016104ad565b6000610f64876115f3565b9050610fab81866040013586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162392505050565b611037576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016104ad565b60008181526033602052604090205460ff16156110d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016104ad565b600081815260336020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055608087015161111f90614e2090613b07565b5a10156111ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c00000000000000000060648201526084016104ad565b8660200151603260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000611211886040015189608001518a606001518b60a001516116ea565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061127690841515815260200190565b60405180910390a25050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156112b457816112b6565b825b90505b92915050565b60008183126112b457816112b6565b60006112b6670de0b6b3a7640000836112e686611704565b6112f091906137f7565b6112fa919061371b565b611948565b6000818310156112b457816112b6565b6000805a90505b825a61132290836136d5565b10156113385761133182613b1f565b9150611316565b505050565b60608160000361138057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113aa578061139481613b1f565b91506113a39050600a836139c8565b9150611384565b60008167ffffffffffffffff8111156113c5576113c561335c565b6040519080825280601f01601f1916602001820160405280156113ef576020820181803683370190505b5090505b8415611472576114046001836136d5565b9150611411600a86613b57565b61141c906030613b07565b60f81b81838151811061143157611431613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061146b600a866139c8565b94506113f3565b949350505050565b600054610100900460ff16611511576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104ad565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b60007f0000000000000000000000000000000000000000000000000000000000000000826020015161158f9190613b07565b421192915050565b600081600001518260200151836040015184606001516040516020016115d6949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a088015193516000976115d6979096959101613b9a565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506116e19101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611b87565b95945050505050565b600080600080845160208601878a8af19695505050505050565b600080821361176f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104ad565b6000606061177c84611bab565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361197957506000919050565b680755bf798b4a1bf1e582126119eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016104ad565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611b9386611c81565b9050611ba181868686611cb3565b9695505050505050565b6000808211611c16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104ad565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611c9d91815260200190565b6040516020818303038152906040529050919050565b6000806000611cc3878686611cf0565b91509150818015611ce557508051602080830191909120875191880191909120145b979650505050505050565b600060606000611cff85611e0b565b90506000806000611d11848a89611f06565b81519295509093509150158080611d255750815b611db1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2070726f76696465642070726f6f6620697320696e60448201527f76616c696400000000000000000000000000000000000000000000000000000060648201526084016104ad565b600081611dcd5760405180602001604052806000815250611df9565b611df986611ddc6001886136d5565b81518110611dec57611dec613b6b565b602002602001015161248f565b919b919a509098505050505050505050565b60606000611e18836124b9565b90506000815167ffffffffffffffff811115611e3657611e3661335c565b604051908082528060200260200182016040528015611e7b57816020015b6040805180820190915260608082526020820152815260200190600190039081611e545790505b50905060005b8251811015611efe576000611eae848381518110611ea157611ea1613b6b565b60200260200101516124ec565b90506040518060400160405280828152602001611eca836124b9565b815250838381518110611edf57611edf613b6b565b6020026020010181905250508080611ef690613b1f565b915050611e81565b509392505050565b60006060818080611f16876125b3565b90506000869050600080611f3d604051806040016040528060608152602001606081525090565b60005b8c5181101561244b578c8181518110611f5b57611f5b613b6b565b602002602001015191508284611f719190613b07565b9350611f7e600188613b07565b965083600003611fff57815180516020909101208514611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016104ad565b61213b565b8151516020116120a157815180516020909101208514611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016104ad565b815185906120ae90613bf1565b1461213b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016104ad565b61214760106001613b07565b826020015151036121b9578551841461244b57600086858151811061216e5761216e613b6b565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061219957612199613b6b565b602002602001015190506121ac81612736565b9650600194505050612439565b6002826020015151036123b15760006121d18361276c565b90506000816000815181106121e8576121e8613b6b565b016020015160f81c905060006121ff600283613c33565b61220a906002613c55565b9050600061221b848360ff16612790565b905060006122298b8a612790565b9050600061223783836127c6565b905060ff85166002148061224e575060ff85166003145b156122a4578083511480156122635750808251145b1561227557612272818b613b07565b99505b507f8000000000000000000000000000000000000000000000000000000000000000995061244b945050505050565b60ff851615806122b7575060ff85166001145b1561232957825181146122f357507f8000000000000000000000000000000000000000000000000000000000000000995061244b945050505050565b61231a886020015160018151811061230d5761230d613b6b565b6020026020010151612736565b9a509750612439945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016104ad565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016104ad565b8061244381613b1f565b915050611f40565b507f800000000000000000000000000000000000000000000000000000000000000084148661247a8786612790565b909e909d50909b509950505050505050505050565b602081015180516060916112b9916124a9906001906136d5565b81518110611ea157611ea1613b6b565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906112b990612872565b606060008060006124fc85612acb565b91945092509050600081600181111561251757612517613c78565b146125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20696e76616c696420524c502062797465732076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6116e185602001518484612fb6565b60606000825160026125c59190613927565b67ffffffffffffffff8111156125dd576125dd61335c565b6040519080825280601f01601f191660200182016040528015612607576020820181803683370190505b50905060005b835181101561272f57600484828151811061262a5761262a613b6b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c8261265f836002613927565b8151811061266f5761266f613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106126b2576126b2613b6b565b01602001516126c4919060f81c613c33565b60f81b826126d3836002613927565b6126de906001613b07565b815181106126ee576126ee613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061272781613b1f565b91505061260d565b5092915050565b600060606020836000015110156127575761275083613094565b9050612763565b612760836124ec565b90505b610beb81613bf1565b60606112b961278b8360200151600081518110611ea157611ea1613b6b565b6125b3565b6060825182106127af57506040805160208101909152600081526112b9565b6112b683838486516127c191906136d5565b61309f565b6000805b8084511180156127da5750808351115b801561285b57508281815181106127f3576127f3613b6b565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061283257612832613b6b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156112b6578061286a81613b1f565b9150506127ca565b606060008061288084612acb565b9193509091506001905081600181111561289c5761289c613c78565b14612929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f524c505265616465723a20696e76616c696420524c50206c6973742076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816129425790505090506000835b8651811015612ac05760208210612a08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2070726f766964656420524c50206c6973742065786360448201527f65656473206d6178206c697374206c656e67746800000000000000000000000060648201526084016104ad565b600080612a456040518060400160405280858c60000151612a2991906136d5565b8152602001858c60200151612a3e9190613b07565b9052612acb565b509150915060405180604001604052808383612a619190613b07565b8152602001848b60200151612a769190613b07565b815250858581518110612a8b57612a8b613b6b565b6020908102919091010152612aa1600185613b07565b9350612aad8183613b07565b612ab79084613b07565b9250505061296f565b508152949350505050565b600080600080846000015111612b63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20524c50206974656d2063616e6e6f74206265206e7560448201527f6c6c00000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6020840151805160001a607f8111612b88576000600160009450945094505050612faf565b60b78111612c44576000612b9d6080836136d5565b905080876000015111612c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f524c505265616465723a20696e76616c696420524c502073686f72742073747260448201527f696e67000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b60019550935060009250612faf915050565b60bf8111612db3576000612c5960b7836136d5565b905080876000015111612cee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67207374726960448201527f6e67206c656e677468000000000000000000000000000000000000000000000060648201526084016104ad565b600183015160208290036101000a9004612d088183613b07565b885111612d97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67207374726960448201527f6e6700000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b612da2826001613b07565b9650945060009350612faf92505050565b60f78111612e6e576000612dc860c0836136d5565b905080876000015111612e5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f524c505265616465723a20696e76616c696420524c502073686f7274206c697360448201527f740000000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b600195509350849250612faf915050565b6000612e7b60f7836136d5565b905080876000015111612f10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67206c69737460448201527f206c656e6774680000000000000000000000000000000000000000000000000060648201526084016104ad565b600183015160208290036101000a9004612f2a8183613b07565b885111612f93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67206c69737460448201526064016104ad565b612f9e826001613b07565b9650945060019350612faf92505050565b9193909250565b606060008267ffffffffffffffff811115612fd357612fd361335c565b6040519080825280601f01601f191660200182016040528015612ffd576020820181803683370190505b5090508051600003613010579050610beb565b600061301c8587613b07565b90506020820160005b6130306020876139c8565b8110156130675782518252613046602084613b07565b9250613053602083613b07565b91508061305f81613b1f565b915050613025565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606112b982613277565b60608182601f01101561310e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104ad565b82828401101561317a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104ad565b818301845110156131e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016104ad565b606082158015613206576040519150600082526020820160405261326e565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561323f578051835260209283019201613227565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60606112b9826020015160008460000151612fb6565b60005b838110156132a8578181015183820152602001613290565b838111156132b7576000848401525b50505050565b600081518084526132d581602086016020860161328d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112b660208301846132bd565b60006020828403121561332c57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461335757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156133ae576133ae61335c565b60405290565b600082601f8301126133c557600080fd5b813567ffffffffffffffff808211156133e0576133e061335c565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156134265761342661335c565b8160405283815286602085880101111561343f57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a0868803121561347757600080fd5b61348086613333565b945060208601359350604086013567ffffffffffffffff80821682146134a557600080fd5b90935060608701359081151582146134bc57600080fd5b909250608087013590808211156134d257600080fd5b506134df888289016133b4565b9150509295509295909350565b6000608082840312156134fe57600080fd5b50919050565b60008083601f84011261351657600080fd5b50813567ffffffffffffffff81111561352e57600080fd5b60208301915083602082850101111561354657600080fd5b9250929050565b600080600080600060e0868803121561356557600080fd5b853567ffffffffffffffff8082111561357d57600080fd5b9087019060c0828a03121561359157600080fd5b61359961338b565b823581526135a960208401613333565b60208201526135ba60408401613333565b6040820152606083013560608201526080830135608082015260a0830135828111156135e557600080fd5b6135f18b8286016133b4565b60a08301525096506020880135955061360d8960408a016134ec565b945060c088013591508082111561362357600080fd5b5061363088828901613504565b969995985093965092949392505050565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161369581604985016020870161328d565b919091016049019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156136e7576136e76136a6565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261372a5761372a6136ec565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561377e5761377e6136a6565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156137bd576137bd6136a6565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156137f1576137f16136a6565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613838576138386136a6565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615613873576138736136a6565b6000871292508782058712848416161561388f5761388f6136a6565b878505871281841616156138a5576138a56136a6565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156138ed576138ed6136a6565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615613921576139216136a6565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561395f5761395f6136a6565b500290565b600067ffffffffffffffff808316818516808303821115613987576139876136a6565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156139bf576139bf6136a6565b02949350505050565b6000826139d7576139d76136ec565b500490565b600084516139ee81846020890161328d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613a2a816001850160208a0161328d565b60019201918201528351613a4581600284016020880161328d565b0160020195945050505050565b600060408284031215613a6457600080fd5b6040516040810181811067ffffffffffffffff82111715613a8757613a8761335c565b604052825181526020928301519281019290925250919050565b600060808284031215613ab357600080fd5b6040516080810181811067ffffffffffffffff82111715613ad657613ad661335c565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b60008219821115613b1a57613b1a6136a6565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613b5057613b506136a6565b5060010190565b600082613b6657613b666136ec565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152613be560c08301846132bd565b98975050505050505050565b805160208083015191908110156134fe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600060ff831680613c4657613c466136ec565b8060ff84160691505092915050565b600060ff821660ff841680821015613c6f57613c6f6136a6565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", } // OptimismPortalABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/optimismportal_more.go b/op-bindings/bindings/optimismportal_more.go index bed776a8e9ee6..0eab13683a839 100644 --- a/op-bindings/bindings/optimismportal_more.go +++ b/op-bindings/bindings/optimismportal_more.go @@ -9,11 +9,11 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const OptimismPortalStorageLayoutJSON = "{\"storage\":[{\"astId\":27112,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":27115,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1404,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1374_storage\"},{\"astId\":1409,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":982,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":995,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_mapping(t_bytes32,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_struct(ResourceParams)1374_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceParams\",\"numberOfBytes\":\"32\"},\"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\"}}}" +const OptimismPortalStorageLayoutJSON = "{\"storage\":[{\"astId\":28013,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":28016,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1401,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1371_storage\"},{\"astId\":1406,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)48_storage\"},{\"astId\":979,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"50\",\"type\":\"t_address\"},{\"astId\":992,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_mapping(t_bytes32,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)48_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[48]\",\"numberOfBytes\":\"1536\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_struct(ResourceParams)1371_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceParams\",\"numberOfBytes\":\"32\"},\"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\"}}}" var OptimismPortalStorageLayout = new(solc.StorageLayout) -var OptimismPortalDeployedBin = "0x6080604052600436106100f65760003560e01c8063a14238e71161008a578063cff0ab9611610059578063cff0ab96146102f7578063e9e05c4214610398578063f4daa291146103ab578063fdc9fe1d146103df57600080fd5b8063a14238e71461026d578063c4fc4798146102ad578063ca3e99ba146102cd578063cd7c9789146102e257600080fd5b80636bb0291e116100c65780636bb0291e146102005780638129fc1c14610215578063867ead131461022a5780639bf62d821461024057600080fd5b80621c2ff61461012257806313620abd1461018057806354fd4d50146101b957806364b79208146101db57600080fd5b3661011d5761011b3334620186a06000604051806020016040528060008152506103ff565b005b600080fd5b34801561012e57600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018c57600080fd5b50610198633b9aca0081565b6040516fffffffffffffffffffffffffffffffff9091168152602001610177565b3480156101c557600080fd5b506101ce6108cc565b6040516101779190613307565b3480156101e757600080fd5b506101f2627a120081565b604051908152602001610177565b34801561020c57600080fd5b506101f2600481565b34801561022157600080fd5b5061011b61096f565b34801561023657600080fd5b506101f261271081565b34801561024c57600080fd5b506033546101569073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027957600080fd5b5061029d61028836600461331a565b60346020526000908152604090205460ff1681565b6040519015158152602001610177565b3480156102b957600080fd5b5061029d6102c836600461331a565b610b2d565b3480156102d957600080fd5b506101f2610bf2565b3480156102ee57600080fd5b506101f2600881565b34801561030357600080fd5b5060015461035f906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610177565b61011b6103a636600461345f565b6103ff565b3480156103b757600080fd5b506101f27f000000000000000000000000000000000000000000000000000000000000000081565b3480156103eb57600080fd5b5061011b6103fa36600461354d565b610c03565b8260005a905083156104b65773ffffffffffffffffffffffffffffffffffffffff8716156104b657604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b333281146104d7575033731111000000000000000000000000000000001111015b600034888888886040516020016104f2959493929190613641565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516105629190613307565b60405180910390a450506001546000906105a2907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436136d5565b9050801561072b5760006105ba6004627a120061371b565b6001546105e59190700100000000000000000000000000000000900467ffffffffffffffff16613783565b9050600060086105f96004627a120061371b565b6001546106199085906fffffffffffffffffffffffffffffffff166137f7565b610623919061371b565b61062d919061371b565b600154909150600090610679906106639061065b9085906fffffffffffffffffffffffffffffffff166138b3565b6127106112a4565b6fffffffffffffffffffffffffffffffff6112bf565b905060018411156106ec576106e9610663670de0b6b3a76400006106d56106a160088361371b565b6106b390670de0b6b3a7640000613783565b6106be60018a6136d5565b6106d090670de0b6b3a7640000613927565b6112ce565b6106df90856137f7565b61065b919061371b565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805484919060109061075e908490700100000000000000000000000000000000900467ffffffffffffffff16613964565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561083a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016104ad565b600154600090610866906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8616613990565b6fffffffffffffffffffffffffffffffff169050600061088a48633b9aca006112ff565b61089490836139c8565b905060005a6108a390866136d5565b9050808211156108bf576108bf6108ba82846136d5565b61130f565b5050505050505050505050565b60606108f77f000000000000000000000000000000000000000000000000000000000000000061133d565b6109207f000000000000000000000000000000000000000000000000000000000000000061133d565b6109497f000000000000000000000000000000000000000000000000000000000000000061133d565b60405160200161095b939291906139dc565b604051602081830303815290604052905090565b600054610100900460ff161580801561098f5750600054600160ff909116105b806109a95750303b1580156109a9575060005460ff166001145b610a35576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104ad565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a9357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610ac761147a565b8015610b2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa158015610bbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be09190613a52565b9050610beb8161155d565b9392505050565b610c006004627a120061371b565b81565b60335473ffffffffffffffffffffffffffffffffffffffff1661dead14610cac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016104ad565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610d6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016104ad565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1c9190613a52565b9050610e278161155d565b610eb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a65640000000000000000000000000000000000000060648201526084016104ad565b610eca610ec536869003860186613aa1565b611597565b815114610f59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016104ad565b6000610f64876115f3565b9050610fab81866040013586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162392505050565b611037576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016104ad565b60008181526034602052604090205460ff16156110d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016104ad565b600081815260346020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055608087015161111f90614e2090613b07565b5a10156111ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c00000000000000000060648201526084016104ad565b8660200151603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000611211886040015189608001518a606001518b60a001516116ea565b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061127690841515815260200190565b60405180910390a25050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156112b457816112b6565b825b90505b92915050565b60008183126112b457816112b6565b60006112b6670de0b6b3a7640000836112e686611704565b6112f091906137f7565b6112fa919061371b565b611948565b6000818310156112b457816112b6565b6000805a90505b825a61132290836136d5565b10156113385761133182613b1f565b9150611316565b505050565b60608160000361138057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113aa578061139481613b1f565b91506113a39050600a836139c8565b9150611384565b60008167ffffffffffffffff8111156113c5576113c561335c565b6040519080825280601f01601f1916602001820160405280156113ef576020820181803683370190505b5090505b8415611472576114046001836136d5565b9150611411600a86613b57565b61141c906030613b07565b60f81b81838151811061143157611431613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061146b600a866139c8565b94506113f3565b949350505050565b600054610100900460ff16611511576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104ad565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b60007f0000000000000000000000000000000000000000000000000000000000000000826020015161158f9190613b07565b421192915050565b600081600001518260200151836040015184606001516040516020016115d6949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a088015193516000976115d6979096959101613b9a565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506116e19101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611b87565b95945050505050565b600080600080845160208601878a8af19695505050505050565b600080821361176f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104ad565b6000606061177c84611bab565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361197957506000919050565b680755bf798b4a1bf1e582126119eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016104ad565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611b9386611c81565b9050611ba181868686611cb3565b9695505050505050565b6000808211611c16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104ad565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611c9d91815260200190565b6040516020818303038152906040529050919050565b6000806000611cc3878686611cf0565b91509150818015611ce557508051602080830191909120875191880191909120145b979650505050505050565b600060606000611cff85611e0b565b90506000806000611d11848a89611f06565b81519295509093509150158080611d255750815b611db1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2070726f76696465642070726f6f6620697320696e60448201527f76616c696400000000000000000000000000000000000000000000000000000060648201526084016104ad565b600081611dcd5760405180602001604052806000815250611df9565b611df986611ddc6001886136d5565b81518110611dec57611dec613b6b565b602002602001015161248f565b919b919a509098505050505050505050565b60606000611e18836124b9565b90506000815167ffffffffffffffff811115611e3657611e3661335c565b604051908082528060200260200182016040528015611e7b57816020015b6040805180820190915260608082526020820152815260200190600190039081611e545790505b50905060005b8251811015611efe576000611eae848381518110611ea157611ea1613b6b565b60200260200101516124ec565b90506040518060400160405280828152602001611eca836124b9565b815250838381518110611edf57611edf613b6b565b6020026020010181905250508080611ef690613b1f565b915050611e81565b509392505050565b60006060818080611f16876125b3565b90506000869050600080611f3d604051806040016040528060608152602001606081525090565b60005b8c5181101561244b578c8181518110611f5b57611f5b613b6b565b602002602001015191508284611f719190613b07565b9350611f7e600188613b07565b965083600003611fff57815180516020909101208514611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016104ad565b61213b565b8151516020116120a157815180516020909101208514611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016104ad565b815185906120ae90613bf1565b1461213b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016104ad565b61214760106001613b07565b826020015151036121b9578551841461244b57600086858151811061216e5761216e613b6b565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061219957612199613b6b565b602002602001015190506121ac81612736565b9650600194505050612439565b6002826020015151036123b15760006121d18361276c565b90506000816000815181106121e8576121e8613b6b565b016020015160f81c905060006121ff600283613c33565b61220a906002613c55565b9050600061221b848360ff16612790565b905060006122298b8a612790565b9050600061223783836127c6565b905060ff85166002148061224e575060ff85166003145b156122a4578083511480156122635750808251145b1561227557612272818b613b07565b99505b507f8000000000000000000000000000000000000000000000000000000000000000995061244b945050505050565b60ff851615806122b7575060ff85166001145b1561232957825181146122f357507f8000000000000000000000000000000000000000000000000000000000000000995061244b945050505050565b61231a886020015160018151811061230d5761230d613b6b565b6020026020010151612736565b9a509750612439945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016104ad565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016104ad565b8061244381613b1f565b915050611f40565b507f800000000000000000000000000000000000000000000000000000000000000084148661247a8786612790565b909e909d50909b509950505050505050505050565b602081015180516060916112b9916124a9906001906136d5565b81518110611ea157611ea1613b6b565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906112b990612872565b606060008060006124fc85612acb565b91945092509050600081600181111561251757612517613c78565b146125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20696e76616c696420524c502062797465732076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6116e185602001518484612fb6565b60606000825160026125c59190613927565b67ffffffffffffffff8111156125dd576125dd61335c565b6040519080825280601f01601f191660200182016040528015612607576020820181803683370190505b50905060005b835181101561272f57600484828151811061262a5761262a613b6b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c8261265f836002613927565b8151811061266f5761266f613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106126b2576126b2613b6b565b01602001516126c4919060f81c613c33565b60f81b826126d3836002613927565b6126de906001613b07565b815181106126ee576126ee613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061272781613b1f565b91505061260d565b5092915050565b600060606020836000015110156127575761275083613094565b9050612763565b612760836124ec565b90505b610beb81613bf1565b60606112b961278b8360200151600081518110611ea157611ea1613b6b565b6125b3565b6060825182106127af57506040805160208101909152600081526112b9565b6112b683838486516127c191906136d5565b61309f565b6000805b8084511180156127da5750808351115b801561285b57508281815181106127f3576127f3613b6b565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061283257612832613b6b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156112b6578061286a81613b1f565b9150506127ca565b606060008061288084612acb565b9193509091506001905081600181111561289c5761289c613c78565b14612929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f524c505265616465723a20696e76616c696420524c50206c6973742076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816129425790505090506000835b8651811015612ac05760208210612a08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2070726f766964656420524c50206c6973742065786360448201527f65656473206d6178206c697374206c656e67746800000000000000000000000060648201526084016104ad565b600080612a456040518060400160405280858c60000151612a2991906136d5565b8152602001858c60200151612a3e9190613b07565b9052612acb565b509150915060405180604001604052808383612a619190613b07565b8152602001848b60200151612a769190613b07565b815250858581518110612a8b57612a8b613b6b565b6020908102919091010152612aa1600185613b07565b9350612aad8183613b07565b612ab79084613b07565b9250505061296f565b508152949350505050565b600080600080846000015111612b63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20524c50206974656d2063616e6e6f74206265206e7560448201527f6c6c00000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6020840151805160001a607f8111612b88576000600160009450945094505050612faf565b60b78111612c44576000612b9d6080836136d5565b905080876000015111612c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f524c505265616465723a20696e76616c696420524c502073686f72742073747260448201527f696e67000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b60019550935060009250612faf915050565b60bf8111612db3576000612c5960b7836136d5565b905080876000015111612cee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67207374726960448201527f6e67206c656e677468000000000000000000000000000000000000000000000060648201526084016104ad565b600183015160208290036101000a9004612d088183613b07565b885111612d97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67207374726960448201527f6e6700000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b612da2826001613b07565b9650945060009350612faf92505050565b60f78111612e6e576000612dc860c0836136d5565b905080876000015111612e5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f524c505265616465723a20696e76616c696420524c502073686f7274206c697360448201527f740000000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b600195509350849250612faf915050565b6000612e7b60f7836136d5565b905080876000015111612f10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67206c69737460448201527f206c656e6774680000000000000000000000000000000000000000000000000060648201526084016104ad565b600183015160208290036101000a9004612f2a8183613b07565b885111612f93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67206c69737460448201526064016104ad565b612f9e826001613b07565b9650945060019350612faf92505050565b9193909250565b606060008267ffffffffffffffff811115612fd357612fd361335c565b6040519080825280601f01601f191660200182016040528015612ffd576020820181803683370190505b5090508051600003613010579050610beb565b600061301c8587613b07565b90506020820160005b6130306020876139c8565b8110156130675782518252613046602084613b07565b9250613053602083613b07565b91508061305f81613b1f565b915050613025565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606112b982613277565b60608182601f01101561310e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104ad565b82828401101561317a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104ad565b818301845110156131e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016104ad565b606082158015613206576040519150600082526020820160405261326e565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561323f578051835260209283019201613227565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60606112b9826020015160008460000151612fb6565b60005b838110156132a8578181015183820152602001613290565b838111156132b7576000848401525b50505050565b600081518084526132d581602086016020860161328d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112b660208301846132bd565b60006020828403121561332c57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461335757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156133ae576133ae61335c565b60405290565b600082601f8301126133c557600080fd5b813567ffffffffffffffff808211156133e0576133e061335c565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156134265761342661335c565b8160405283815286602085880101111561343f57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a0868803121561347757600080fd5b61348086613333565b945060208601359350604086013567ffffffffffffffff80821682146134a557600080fd5b90935060608701359081151582146134bc57600080fd5b909250608087013590808211156134d257600080fd5b506134df888289016133b4565b9150509295509295909350565b6000608082840312156134fe57600080fd5b50919050565b60008083601f84011261351657600080fd5b50813567ffffffffffffffff81111561352e57600080fd5b60208301915083602082850101111561354657600080fd5b9250929050565b600080600080600060e0868803121561356557600080fd5b853567ffffffffffffffff8082111561357d57600080fd5b9087019060c0828a03121561359157600080fd5b61359961338b565b823581526135a960208401613333565b60208201526135ba60408401613333565b6040820152606083013560608201526080830135608082015260a0830135828111156135e557600080fd5b6135f18b8286016133b4565b60a08301525096506020880135955061360d8960408a016134ec565b945060c088013591508082111561362357600080fd5b5061363088828901613504565b969995985093965092949392505050565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161369581604985016020870161328d565b919091016049019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156136e7576136e76136a6565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261372a5761372a6136ec565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561377e5761377e6136a6565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156137bd576137bd6136a6565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156137f1576137f16136a6565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613838576138386136a6565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615613873576138736136a6565b6000871292508782058712848416161561388f5761388f6136a6565b878505871281841616156138a5576138a56136a6565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156138ed576138ed6136a6565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615613921576139216136a6565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561395f5761395f6136a6565b500290565b600067ffffffffffffffff808316818516808303821115613987576139876136a6565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156139bf576139bf6136a6565b02949350505050565b6000826139d7576139d76136ec565b500490565b600084516139ee81846020890161328d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613a2a816001850160208a0161328d565b60019201918201528351613a4581600284016020880161328d565b0160020195945050505050565b600060408284031215613a6457600080fd5b6040516040810181811067ffffffffffffffff82111715613a8757613a8761335c565b604052825181526020928301519281019290925250919050565b600060808284031215613ab357600080fd5b6040516080810181811067ffffffffffffffff82111715613ad657613ad661335c565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b60008219821115613b1a57613b1a6136a6565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613b5057613b506136a6565b5060010190565b600082613b6657613b666136ec565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152613be560c08301846132bd565b98975050505050505050565b805160208083015191908110156134fe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600060ff831680613c4657613c466136ec565b8060ff84160691505092915050565b600060ff821660ff841680821015613c6f57613c6f6136a6565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a" +var OptimismPortalDeployedBin = "0x6080604052600436106100f65760003560e01c8063a14238e71161008a578063cff0ab9611610059578063cff0ab96146102f7578063e9e05c4214610398578063f4daa291146103ab578063fdc9fe1d146103df57600080fd5b8063a14238e71461026d578063c4fc4798146102ad578063ca3e99ba146102cd578063cd7c9789146102e257600080fd5b80636bb0291e116100c65780636bb0291e146102005780638129fc1c14610215578063867ead131461022a5780639bf62d821461024057600080fd5b80621c2ff61461012257806313620abd1461018057806354fd4d50146101b957806364b79208146101db57600080fd5b3661011d5761011b3334620186a06000604051806020016040528060008152506103ff565b005b600080fd5b34801561012e57600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018c57600080fd5b50610198633b9aca0081565b6040516fffffffffffffffffffffffffffffffff9091168152602001610177565b3480156101c557600080fd5b506101ce6108cc565b6040516101779190613307565b3480156101e757600080fd5b506101f2627a120081565b604051908152602001610177565b34801561020c57600080fd5b506101f2600481565b34801561022157600080fd5b5061011b61096f565b34801561023657600080fd5b506101f261271081565b34801561024c57600080fd5b506032546101569073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027957600080fd5b5061029d61028836600461331a565b60336020526000908152604090205460ff1681565b6040519015158152602001610177565b3480156102b957600080fd5b5061029d6102c836600461331a565b610b2d565b3480156102d957600080fd5b506101f2610bf2565b3480156102ee57600080fd5b506101f2600881565b34801561030357600080fd5b5060015461035f906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610177565b61011b6103a636600461345f565b6103ff565b3480156103b757600080fd5b506101f27f000000000000000000000000000000000000000000000000000000000000000081565b3480156103eb57600080fd5b5061011b6103fa36600461354d565b610c03565b8260005a905083156104b65773ffffffffffffffffffffffffffffffffffffffff8716156104b657604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b333281146104d7575033731111000000000000000000000000000000001111015b600034888888886040516020016104f2959493929190613641565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516105629190613307565b60405180910390a450506001546000906105a2907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436136d5565b9050801561072b5760006105ba6004627a120061371b565b6001546105e59190700100000000000000000000000000000000900467ffffffffffffffff16613783565b9050600060086105f96004627a120061371b565b6001546106199085906fffffffffffffffffffffffffffffffff166137f7565b610623919061371b565b61062d919061371b565b600154909150600090610679906106639061065b9085906fffffffffffffffffffffffffffffffff166138b3565b6127106112a4565b6fffffffffffffffffffffffffffffffff6112bf565b905060018411156106ec576106e9610663670de0b6b3a76400006106d56106a160088361371b565b6106b390670de0b6b3a7640000613783565b6106be60018a6136d5565b6106d090670de0b6b3a7640000613927565b6112ce565b6106df90856137f7565b61065b919061371b565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805484919060109061075e908490700100000000000000000000000000000000900467ffffffffffffffff16613964565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561083a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016104ad565b600154600090610866906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8616613990565b6fffffffffffffffffffffffffffffffff169050600061088a48633b9aca006112ff565b61089490836139c8565b905060005a6108a390866136d5565b9050808211156108bf576108bf6108ba82846136d5565b61130f565b5050505050505050505050565b60606108f77f000000000000000000000000000000000000000000000000000000000000000061133d565b6109207f000000000000000000000000000000000000000000000000000000000000000061133d565b6109497f000000000000000000000000000000000000000000000000000000000000000061133d565b60405160200161095b939291906139dc565b604051602081830303815290604052905090565b600054610100900460ff161580801561098f5750600054600160ff909116105b806109a95750303b1580156109a9575060005460ff166001145b610a35576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104ad565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a9357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610ac761147a565b8015610b2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa158015610bbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be09190613a52565b9050610beb8161155d565b9392505050565b610c006004627a120061371b565b81565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610cac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016104ad565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610d6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016104ad565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1c9190613a52565b9050610e278161155d565b610eb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a65640000000000000000000000000000000000000060648201526084016104ad565b610eca610ec536869003860186613aa1565b611597565b815114610f59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016104ad565b6000610f64876115f3565b9050610fab81866040013586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162392505050565b611037576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016104ad565b60008181526033602052604090205460ff16156110d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016104ad565b600081815260336020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055608087015161111f90614e2090613b07565b5a10156111ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c00000000000000000060648201526084016104ad565b8660200151603260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000611211886040015189608001518a606001518b60a001516116ea565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061127690841515815260200190565b60405180910390a25050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156112b457816112b6565b825b90505b92915050565b60008183126112b457816112b6565b60006112b6670de0b6b3a7640000836112e686611704565b6112f091906137f7565b6112fa919061371b565b611948565b6000818310156112b457816112b6565b6000805a90505b825a61132290836136d5565b10156113385761133182613b1f565b9150611316565b505050565b60608160000361138057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113aa578061139481613b1f565b91506113a39050600a836139c8565b9150611384565b60008167ffffffffffffffff8111156113c5576113c561335c565b6040519080825280601f01601f1916602001820160405280156113ef576020820181803683370190505b5090505b8415611472576114046001836136d5565b9150611411600a86613b57565b61141c906030613b07565b60f81b81838151811061143157611431613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061146b600a866139c8565b94506113f3565b949350505050565b600054610100900460ff16611511576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104ad565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b60007f0000000000000000000000000000000000000000000000000000000000000000826020015161158f9190613b07565b421192915050565b600081600001518260200151836040015184606001516040516020016115d6949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a088015193516000976115d6979096959101613b9a565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506116e19101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611b87565b95945050505050565b600080600080845160208601878a8af19695505050505050565b600080821361176f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104ad565b6000606061177c84611bab565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361197957506000919050565b680755bf798b4a1bf1e582126119eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016104ad565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611b9386611c81565b9050611ba181868686611cb3565b9695505050505050565b6000808211611c16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104ad565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611c9d91815260200190565b6040516020818303038152906040529050919050565b6000806000611cc3878686611cf0565b91509150818015611ce557508051602080830191909120875191880191909120145b979650505050505050565b600060606000611cff85611e0b565b90506000806000611d11848a89611f06565b81519295509093509150158080611d255750815b611db1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2070726f76696465642070726f6f6620697320696e60448201527f76616c696400000000000000000000000000000000000000000000000000000060648201526084016104ad565b600081611dcd5760405180602001604052806000815250611df9565b611df986611ddc6001886136d5565b81518110611dec57611dec613b6b565b602002602001015161248f565b919b919a509098505050505050505050565b60606000611e18836124b9565b90506000815167ffffffffffffffff811115611e3657611e3661335c565b604051908082528060200260200182016040528015611e7b57816020015b6040805180820190915260608082526020820152815260200190600190039081611e545790505b50905060005b8251811015611efe576000611eae848381518110611ea157611ea1613b6b565b60200260200101516124ec565b90506040518060400160405280828152602001611eca836124b9565b815250838381518110611edf57611edf613b6b565b6020026020010181905250508080611ef690613b1f565b915050611e81565b509392505050565b60006060818080611f16876125b3565b90506000869050600080611f3d604051806040016040528060608152602001606081525090565b60005b8c5181101561244b578c8181518110611f5b57611f5b613b6b565b602002602001015191508284611f719190613b07565b9350611f7e600188613b07565b965083600003611fff57815180516020909101208514611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016104ad565b61213b565b8151516020116120a157815180516020909101208514611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016104ad565b815185906120ae90613bf1565b1461213b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016104ad565b61214760106001613b07565b826020015151036121b9578551841461244b57600086858151811061216e5761216e613b6b565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061219957612199613b6b565b602002602001015190506121ac81612736565b9650600194505050612439565b6002826020015151036123b15760006121d18361276c565b90506000816000815181106121e8576121e8613b6b565b016020015160f81c905060006121ff600283613c33565b61220a906002613c55565b9050600061221b848360ff16612790565b905060006122298b8a612790565b9050600061223783836127c6565b905060ff85166002148061224e575060ff85166003145b156122a4578083511480156122635750808251145b1561227557612272818b613b07565b99505b507f8000000000000000000000000000000000000000000000000000000000000000995061244b945050505050565b60ff851615806122b7575060ff85166001145b1561232957825181146122f357507f8000000000000000000000000000000000000000000000000000000000000000995061244b945050505050565b61231a886020015160018151811061230d5761230d613b6b565b6020026020010151612736565b9a509750612439945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016104ad565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016104ad565b8061244381613b1f565b915050611f40565b507f800000000000000000000000000000000000000000000000000000000000000084148661247a8786612790565b909e909d50909b509950505050505050505050565b602081015180516060916112b9916124a9906001906136d5565b81518110611ea157611ea1613b6b565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906112b990612872565b606060008060006124fc85612acb565b91945092509050600081600181111561251757612517613c78565b146125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20696e76616c696420524c502062797465732076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6116e185602001518484612fb6565b60606000825160026125c59190613927565b67ffffffffffffffff8111156125dd576125dd61335c565b6040519080825280601f01601f191660200182016040528015612607576020820181803683370190505b50905060005b835181101561272f57600484828151811061262a5761262a613b6b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c8261265f836002613927565b8151811061266f5761266f613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106126b2576126b2613b6b565b01602001516126c4919060f81c613c33565b60f81b826126d3836002613927565b6126de906001613b07565b815181106126ee576126ee613b6b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061272781613b1f565b91505061260d565b5092915050565b600060606020836000015110156127575761275083613094565b9050612763565b612760836124ec565b90505b610beb81613bf1565b60606112b961278b8360200151600081518110611ea157611ea1613b6b565b6125b3565b6060825182106127af57506040805160208101909152600081526112b9565b6112b683838486516127c191906136d5565b61309f565b6000805b8084511180156127da5750808351115b801561285b57508281815181106127f3576127f3613b6b565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061283257612832613b6b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156112b6578061286a81613b1f565b9150506127ca565b606060008061288084612acb565b9193509091506001905081600181111561289c5761289c613c78565b14612929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f524c505265616465723a20696e76616c696420524c50206c6973742076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816129425790505090506000835b8651811015612ac05760208210612a08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2070726f766964656420524c50206c6973742065786360448201527f65656473206d6178206c697374206c656e67746800000000000000000000000060648201526084016104ad565b600080612a456040518060400160405280858c60000151612a2991906136d5565b8152602001858c60200151612a3e9190613b07565b9052612acb565b509150915060405180604001604052808383612a619190613b07565b8152602001848b60200151612a769190613b07565b815250858581518110612a8b57612a8b613b6b565b6020908102919091010152612aa1600185613b07565b9350612aad8183613b07565b612ab79084613b07565b9250505061296f565b508152949350505050565b600080600080846000015111612b63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20524c50206974656d2063616e6e6f74206265206e7560448201527f6c6c00000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b6020840151805160001a607f8111612b88576000600160009450945094505050612faf565b60b78111612c44576000612b9d6080836136d5565b905080876000015111612c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f524c505265616465723a20696e76616c696420524c502073686f72742073747260448201527f696e67000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b60019550935060009250612faf915050565b60bf8111612db3576000612c5960b7836136d5565b905080876000015111612cee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67207374726960448201527f6e67206c656e677468000000000000000000000000000000000000000000000060648201526084016104ad565b600183015160208290036101000a9004612d088183613b07565b885111612d97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67207374726960448201527f6e6700000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b612da2826001613b07565b9650945060009350612faf92505050565b60f78111612e6e576000612dc860c0836136d5565b905080876000015111612e5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f524c505265616465723a20696e76616c696420524c502073686f7274206c697360448201527f740000000000000000000000000000000000000000000000000000000000000060648201526084016104ad565b600195509350849250612faf915050565b6000612e7b60f7836136d5565b905080876000015111612f10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67206c69737460448201527f206c656e6774680000000000000000000000000000000000000000000000000060648201526084016104ad565b600183015160208290036101000a9004612f2a8183613b07565b885111612f93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f524c505265616465723a20696e76616c696420524c50206c6f6e67206c69737460448201526064016104ad565b612f9e826001613b07565b9650945060019350612faf92505050565b9193909250565b606060008267ffffffffffffffff811115612fd357612fd361335c565b6040519080825280601f01601f191660200182016040528015612ffd576020820181803683370190505b5090508051600003613010579050610beb565b600061301c8587613b07565b90506020820160005b6130306020876139c8565b8110156130675782518252613046602084613b07565b9250613053602083613b07565b91508061305f81613b1f565b915050613025565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606112b982613277565b60608182601f01101561310e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104ad565b82828401101561317a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104ad565b818301845110156131e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016104ad565b606082158015613206576040519150600082526020820160405261326e565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561323f578051835260209283019201613227565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60606112b9826020015160008460000151612fb6565b60005b838110156132a8578181015183820152602001613290565b838111156132b7576000848401525b50505050565b600081518084526132d581602086016020860161328d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112b660208301846132bd565b60006020828403121561332c57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461335757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156133ae576133ae61335c565b60405290565b600082601f8301126133c557600080fd5b813567ffffffffffffffff808211156133e0576133e061335c565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156134265761342661335c565b8160405283815286602085880101111561343f57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a0868803121561347757600080fd5b61348086613333565b945060208601359350604086013567ffffffffffffffff80821682146134a557600080fd5b90935060608701359081151582146134bc57600080fd5b909250608087013590808211156134d257600080fd5b506134df888289016133b4565b9150509295509295909350565b6000608082840312156134fe57600080fd5b50919050565b60008083601f84011261351657600080fd5b50813567ffffffffffffffff81111561352e57600080fd5b60208301915083602082850101111561354657600080fd5b9250929050565b600080600080600060e0868803121561356557600080fd5b853567ffffffffffffffff8082111561357d57600080fd5b9087019060c0828a03121561359157600080fd5b61359961338b565b823581526135a960208401613333565b60208201526135ba60408401613333565b6040820152606083013560608201526080830135608082015260a0830135828111156135e557600080fd5b6135f18b8286016133b4565b60a08301525096506020880135955061360d8960408a016134ec565b945060c088013591508082111561362357600080fd5b5061363088828901613504565b969995985093965092949392505050565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161369581604985016020870161328d565b919091016049019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156136e7576136e76136a6565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261372a5761372a6136ec565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561377e5761377e6136a6565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156137bd576137bd6136a6565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156137f1576137f16136a6565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613838576138386136a6565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615613873576138736136a6565b6000871292508782058712848416161561388f5761388f6136a6565b878505871281841616156138a5576138a56136a6565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156138ed576138ed6136a6565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615613921576139216136a6565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561395f5761395f6136a6565b500290565b600067ffffffffffffffff808316818516808303821115613987576139876136a6565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156139bf576139bf6136a6565b02949350505050565b6000826139d7576139d76136ec565b500490565b600084516139ee81846020890161328d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613a2a816001850160208a0161328d565b60019201918201528351613a4581600284016020880161328d565b0160020195945050505050565b600060408284031215613a6457600080fd5b6040516040810181811067ffffffffffffffff82111715613a8757613a8761335c565b604052825181526020928301519281019290925250919050565b600060808284031215613ab357600080fd5b6040516080810181811067ffffffffffffffff82111715613ad657613ad661335c565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b60008219821115613b1a57613b1a6136a6565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613b5057613b506136a6565b5060010190565b600082613b6657613b666136ec565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152613be560c08301846132bd565b98975050505050505050565b805160208083015191908110156134fe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600060ff831680613c4657613c466136ec565b8060ff84160691505092915050565b600060ff821660ff841680821015613c6f57613c6f6136a6565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(OptimismPortalStorageLayoutJSON), OptimismPortalStorageLayout); err != nil { diff --git a/op-bindings/bindings/sequencerfeevault_more.go b/op-bindings/bindings/sequencerfeevault_more.go index e5508bac63a3e..900582316c9cd 100644 --- a/op-bindings/bindings/sequencerfeevault_more.go +++ b/op-bindings/bindings/sequencerfeevault_more.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const SequencerFeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":2694,\"contract\":\"contracts/L2/SequencerFeeVault.sol:SequencerFeeVault\",\"label\":\"l1FeeWallet\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"}}}" +const SequencerFeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":2691,\"contract\":\"contracts/L2/SequencerFeeVault.sol:SequencerFeeVault\",\"label\":\"l1FeeWallet\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"}}}" var SequencerFeeVaultStorageLayout = new(solc.StorageLayout) diff --git a/op-chain-ops/crossdomain/alias.go b/op-chain-ops/crossdomain/alias.go index e4b78d2e20b4f..91e64b47ab962 100644 --- a/op-chain-ops/crossdomain/alias.go +++ b/op-chain-ops/crossdomain/alias.go @@ -7,27 +7,27 @@ import ( ) var ( - uint160Max, _ = uint256.FromHex("0xffffffffffffffffffffffffffffffffffffffff") - offset = new(uint256.Int).SetBytes(common.HexToAddress("0x1111000000000000000000000000000000001111").Bytes()) + offsetAddr = common.HexToAddress("0x1111000000000000000000000000000000001111") + offsetU256 = new(uint256.Int).SetBytes20(offsetAddr[:]) ) // ApplyL1ToL2Alias will apply the alias applied to L1 to L2 messages when it // originates from a contract address -func ApplyL1ToL2Alias(address *common.Address) *common.Address { - input := new(uint256.Int).SetBytes(address.Bytes()) - output := new(uint256.Int).AddMod(input, offset, uint160Max) - if output.Cmp(input) < 0 { - output = output.Sub(output, new(uint256.Int).SetUint64(1)) - } - addr := common.BigToAddress(output.ToBig()) - return &addr +func ApplyL1ToL2Alias(address common.Address) common.Address { + var input uint256.Int + input.SetBytes20(address[:]) + input.Add(&input, offsetU256) + // clipping to bytes20 is the same as modulo 160 here, since the modulo is a multiple of 8 bits + return input.Bytes20() } // UndoL1ToL2Alias will remove the alias applied to L1 to L2 messages when it // originates from a contract address -func UndoL1ToL2Alias(address *common.Address) *common.Address { - input := new(uint256.Int).SetBytes(address.Bytes()) - output := new(uint256.Int).Sub(input, offset) - addr := common.BigToAddress(output.ToBig()) - return &addr +func UndoL1ToL2Alias(address common.Address) common.Address { + var input uint256.Int + input.SetBytes20(address[:]) + input.Sub(&input, offsetU256) + // clipping to bytes20 is the same as modulo 160 here, since the modulo is a multiple of 8 bits. + // and underflows are not affected either. + return input.Bytes20() } diff --git a/op-chain-ops/crossdomain/alias_test.go b/op-chain-ops/crossdomain/alias_test.go index 1351a57f1ddd7..16bb77d39e5d4 100644 --- a/op-chain-ops/crossdomain/alias_test.go +++ b/op-chain-ops/crossdomain/alias_test.go @@ -4,17 +4,18 @@ import ( "fmt" "testing" - "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" ) func FuzzAliasing(f *testing.F) { f.Fuzz(func(t *testing.T, address []byte) { addr := common.BytesToAddress(address) - aliased := crossdomain.ApplyL1ToL2Alias(&addr) + aliased := crossdomain.ApplyL1ToL2Alias(addr) unaliased := crossdomain.UndoL1ToL2Alias(aliased) - require.Equal(t, addr, *unaliased) + require.Equal(t, addr, unaliased) }) } @@ -51,10 +52,10 @@ func TestAliasing(t *testing.T) { for i, test := range cases { t.Run(fmt.Sprintf("test%d", i), func(t *testing.T) { - aliased := crossdomain.ApplyL1ToL2Alias(&test.Input) - require.Equal(t, test.Output, *aliased) + aliased := crossdomain.ApplyL1ToL2Alias(test.Input) + require.Equal(t, test.Output, aliased) unaliased := crossdomain.UndoL1ToL2Alias(aliased) - require.Equal(t, test.Input, *unaliased) + require.Equal(t, test.Input, unaliased) }) } } diff --git a/op-chain-ops/deployer/deployer.go b/op-chain-ops/deployer/deployer.go index c2f0056ef7ac5..04efe2bbce147 100644 --- a/op-chain-ops/deployer/deployer.go +++ b/op-chain-ops/deployer/deployer.go @@ -113,7 +113,7 @@ func Deploy(backend *backends.SimulatedBackend, constructors []Constructor, cb D backend.Commit() addr, err := bind.WaitDeployed(ctx, backend, tx) if err != nil { - return nil, err + return nil, fmt.Errorf("%s: %w", deployment.Name, err) } if addr == (common.Address{}) { diff --git a/op-chain-ops/genesis/config.go b/op-chain-ops/genesis/config.go index 336a8ea5811d5..c7aba95acb611 100644 --- a/op-chain-ops/genesis/config.go +++ b/op-chain-ops/genesis/config.go @@ -2,6 +2,7 @@ package genesis import ( "encoding/json" + "errors" "os" "path/filepath" @@ -120,6 +121,13 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block, proxyL1Stand func NewL2StorageConfig(config *DeployConfig, block *types.Block, proxyL1StandardBridge common.Address, proxyL1CrossDomainMessenger common.Address) (state.StorageConfig, error) { storage := make(state.StorageConfig) + if block.Number() == nil { + return storage, errors.New("block number not set") + } + if block.BaseFee() == nil { + return storage, errors.New("block base fee not set") + } + storage["L2ToL1MessagePasser"] = state.StorageValues{ "nonce": 0, } diff --git a/op-chain-ops/genesis/helpers.go b/op-chain-ops/genesis/helpers.go index 036f05b7e2a54..cfa2833e95530 100644 --- a/op-chain-ops/genesis/helpers.go +++ b/op-chain-ops/genesis/helpers.go @@ -57,6 +57,8 @@ var DevAccounts = []common.Address{ common.HexToAddress("0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097"), common.HexToAddress("0xde3829a23df1479438622a08a116e8eb3f620bb5"), common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"), + // Test account used by geth tests + common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"), } // The devBalance is the amount of wei that a dev account is funded with. diff --git a/op-chain-ops/genesis/layer_one.go b/op-chain-ops/genesis/layer_one.go index cceb035f5b1ba..7ad9aca3da7f4 100644 --- a/op-chain-ops/genesis/layer_one.go +++ b/op-chain-ops/genesis/layer_one.go @@ -73,7 +73,6 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) { data, err := l2ooABI.Pack( "initialize", config.L2OutputOracleGenesisL2Output, - big.NewInt(0), config.L2OutputOracleProposer, config.L2OutputOracleOwner, ) diff --git a/op-chain-ops/genesis/layer_two.go b/op-chain-ops/genesis/layer_two.go index f1726a06afdb3..fc50f9711dd9b 100644 --- a/op-chain-ops/genesis/layer_two.go +++ b/op-chain-ops/genesis/layer_two.go @@ -1,6 +1,7 @@ package genesis import ( + "github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-chain-ops/state" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -29,6 +30,14 @@ func BuildL2DeveloperGenesis(config *DeployConfig, l1StartBlock *types.Block, l2 } SetPrecompileBalances(db) + if l2Addrs == nil { + l2Addrs = &L2Addresses{ + ProxyAdmin: predeploys.DevProxyAdminAddr, + L1StandardBridgeProxy: predeploys.DevL1StandardBridgeAddr, + L1CrossDomainMessengerProxy: predeploys.DevL1CrossDomainMessengerAddr, + } + } + return BuildL2Genesis(db, config, l1StartBlock, l2Addrs) } diff --git a/op-chain-ops/genesis/layer_two_test.go b/op-chain-ops/genesis/layer_two_test.go index 4fb4f72d02023..8db45e833113c 100644 --- a/op-chain-ops/genesis/layer_two_test.go +++ b/op-chain-ops/genesis/layer_two_test.go @@ -77,7 +77,7 @@ func TestBuildL2DeveloperGenesis(t *testing.T) { require.Equal(t, adminSlot, proxyAdmin.Address.Hash()) require.Equal(t, account.Code, depB) } - require.Equal(t, 2338, len(gen.Alloc)) + require.Equal(t, 2339, len(gen.Alloc)) if writeFile { file, _ := json.MarshalIndent(gen, "", " ") diff --git a/op-chain-ops/go.mod b/op-chain-ops/go.mod index 13252850671ce..8680f4af93658 100644 --- a/op-chain-ops/go.mod +++ b/op-chain-ops/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220820030939-de38b6f6f77e - github.com/ethereum-optimism/optimism/op-bindings v0.8.8 + github.com/ethereum-optimism/optimism/op-bindings v0.8.10 github.com/ethereum/go-ethereum v1.10.23 github.com/holiman/uint256 v1.2.0 github.com/mattn/go-isatty v0.0.14 diff --git a/op-chain-ops/go.sum b/op-chain-ops/go.sum index 3f5353abd5725..5ee82bd36eba6 100644 --- a/op-chain-ops/go.sum +++ b/op-chain-ops/go.sum @@ -176,8 +176,8 @@ github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd h1:NchOn github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220820030939-de38b6f6f77e h1:LUfy9ofKcen9Cm1T9JyGNnrPLR2AmyelFbohS6bs4X8= github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220820030939-de38b6f6f77e/go.mod h1:Oj5A6Qs/Ao1SP17i3uKroyhz49q/ehagSXRAlvwaI5Y= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8 h1:HN625JI2VsRsli+U6GAXipg7lAKx8EOmGIovN79Az+I= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10 h1:aSAWCQwBQnbmv03Gvtuvn3qfTWrZu/sTlRAWrpQhiHc= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= diff --git a/op-e2e/actions/action.go b/op-e2e/actions/action.go index a578c6ad55261..c4e86b2b15f7f 100644 --- a/op-e2e/actions/action.go +++ b/op-e2e/actions/action.go @@ -44,6 +44,22 @@ type defaultTesting struct { state ActionStatus } +type StatefulTesting interface { + Testing + Reset(actionCtx context.Context) + State() ActionStatus +} + +// NewDefaultTesting returns a new testing obj. +// Returns an interface, we're likely changing the behavior here as we build more action tests. +func NewDefaultTesting(tb e2eutils.TestingBase) StatefulTesting { + return &defaultTesting{ + TestingBase: tb, + ctx: context.Background(), + state: ActionOK, + } +} + // Ctx shares a context to execute an action with, the test runner may interrupt the action without stopping the test. func (st *defaultTesting) Ctx() context.Context { return st.ctx diff --git a/op-e2e/actions/l1_miner.go b/op-e2e/actions/l1_miner.go new file mode 100644 index 0000000000000..aaeecfb56daff --- /dev/null +++ b/op-e2e/actions/l1_miner.go @@ -0,0 +1,156 @@ +package actions + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/misc" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" +) + +// L1Miner wraps a L1Replica with instrumented block building ability. +type L1Miner struct { + L1Replica + + // L1 block building preferences + prefCoinbase common.Address + + // L1 block building data + l1BuildingHeader *types.Header // block header that we add txs to for block building + l1BuildingState *state.StateDB // state used for block building + l1GasPool *core.GasPool // track gas used of ongoing building + pendingIndices map[common.Address]uint64 // per account, how many txs from the pool were already included in the block, since the pool is lagging behind block mining. + l1Transactions []*types.Transaction // collects txs that were successfully included into current block build + l1Receipts []*types.Receipt // collect receipts of ongoing building + l1Building bool + l1TxFailed []*types.Transaction // log of failed transactions which could not be included +} + +// NewL1Miner creates a new L1Replica that can also build blocks. +func NewL1Miner(log log.Logger, genesis *core.Genesis) *L1Miner { + rep := NewL1Replica(log, genesis) + return &L1Miner{ + L1Replica: *rep, + } +} + +// ActL1StartBlock returns an action to build a new L1 block on top of the head block, +// with timeDelta added to the head block time. +func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action { + return func(t Testing) { + if s.l1Building { + t.InvalidAction("not valid if we already started building a block") + } + if timeDelta == 0 { + t.Fatalf("invalid time delta: %d", timeDelta) + } + + parent := s.l1Chain.CurrentHeader() + parentHash := parent.Hash() + statedb, err := state.New(parent.Root, state.NewDatabase(s.l1Database), nil) + if err != nil { + t.Fatalf("failed to init state db around block %s (state %s): %w", parentHash, parent.Root, err) + } + header := &types.Header{ + ParentHash: parentHash, + Coinbase: s.prefCoinbase, + Difficulty: common.Big0, + Number: new(big.Int).Add(parent.Number, common.Big1), + GasLimit: parent.GasLimit, + Time: parent.Time + timeDelta, + Extra: []byte("L1 was here"), + MixDigest: common.Hash{}, // TODO: maybe randomize this (prev-randao value) + } + if s.l1Cfg.Config.IsLondon(header.Number) { + header.BaseFee = misc.CalcBaseFee(s.l1Cfg.Config, parent) + // At the transition, double the gas limit so the gas target is equal to the old gas limit. + if !s.l1Cfg.Config.IsLondon(parent.Number) { + header.GasLimit = parent.GasLimit * params.ElasticityMultiplier + } + } + + s.l1Building = true + s.l1BuildingHeader = header + s.l1BuildingState = statedb + s.l1Receipts = make([]*types.Receipt, 0) + s.l1Transactions = make([]*types.Transaction, 0) + s.pendingIndices = make(map[common.Address]uint64) + + s.l1GasPool = new(core.GasPool).AddGas(header.GasLimit) + } +} + +// ActL1IncludeTx includes the next tx from L1 tx pool from the given account +func (s *L1Miner) ActL1IncludeTx(from common.Address) Action { + return func(t Testing) { + if !s.l1Building { + t.InvalidAction("no tx inclusion when not building l1 block") + return + } + i := s.pendingIndices[from] + txs, q := s.eth.TxPool().ContentFrom(from) + if uint64(len(txs)) <= i { + t.Fatalf("no pending txs from %s, and have %d unprocessable queued txs from this account", from, len(q)) + } + tx := txs[i] + if tx.Gas() > s.l1BuildingHeader.GasLimit { + t.Fatalf("tx consumes %d gas, more than available in L1 block %d", tx.Gas(), s.l1BuildingHeader.GasLimit) + } + if tx.Gas() > uint64(*s.l1GasPool) { + t.InvalidAction("action takes too much gas: %d, only have %d", tx.Gas(), uint64(*s.l1GasPool)) + return + } + s.pendingIndices[from] = i + 1 // won't retry the tx + receipt, err := core.ApplyTransaction(s.l1Cfg.Config, s.l1Chain, &s.l1BuildingHeader.Coinbase, + s.l1GasPool, s.l1BuildingState, s.l1BuildingHeader, tx, &s.l1BuildingHeader.GasUsed, *s.l1Chain.GetVMConfig()) + if err != nil { + s.l1TxFailed = append(s.l1TxFailed, tx) + t.Fatalf("failed to apply transaction to L1 block (tx %d): %w", len(s.l1Transactions), err) + } + s.l1Receipts = append(s.l1Receipts, receipt) + s.l1Transactions = append(s.l1Transactions, tx) + } +} + +func (s *L1Miner) ActL1SetFeeRecipient(coinbase common.Address) { + s.prefCoinbase = coinbase + if s.l1Building { + s.l1BuildingHeader.Coinbase = coinbase + } +} + +// ActL1EndBlock finishes the new L1 block, and applies it to the chain as unsafe block +func (s *L1Miner) ActL1EndBlock(t Testing) { + if !s.l1Building { + t.InvalidAction("cannot end L1 block when not building block") + return + } + + s.l1Building = false + s.l1BuildingHeader.GasUsed = s.l1BuildingHeader.GasLimit - uint64(*s.l1GasPool) + s.l1BuildingHeader.Root = s.l1BuildingState.IntermediateRoot(s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number)) + block := types.NewBlock(s.l1BuildingHeader, s.l1Transactions, nil, s.l1Receipts, trie.NewStackTrie(nil)) + + // Write state changes to db + root, err := s.l1BuildingState.Commit(s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number)) + if err != nil { + t.Fatalf("l1 state write error: %v", err) + } + if err := s.l1BuildingState.Database().TrieDB().Commit(root, false, nil); err != nil { + t.Fatalf("l1 trie write error: %v", err) + } + + _, err = s.l1Chain.InsertChain(types.Blocks{block}) + if err != nil { + t.Fatalf("failed to insert block into l1 chain") + } +} + +func (s *L1Miner) Close() error { + return s.L1Replica.Close() +} diff --git a/op-e2e/actions/l1_miner_test.go b/op-e2e/actions/l1_miner_test.go new file mode 100644 index 0000000000000..8d4c790b8310e --- /dev/null +++ b/op-e2e/actions/l1_miner_test.go @@ -0,0 +1,65 @@ +package actions + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/testlog" +) + +func TestL1Miner_BuildBlock(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlDebug) + miner := NewL1Miner(log, sd.L1Cfg) + t.Cleanup(func() { + _ = miner.Close() + }) + + cl := miner.EthClient() + signer := types.LatestSigner(sd.L1Cfg.Config) + + // send a tx to the miner + tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L1Cfg.Config.ChainID, + Nonce: 0, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), + }) + require.NoError(gt, cl.SendTransaction(t.Ctx(), tx)) + + // make an empty block, even though a tx may be waiting + miner.ActL1StartBlock(10)(t) + miner.ActL1EndBlock(t) + bl := miner.l1Chain.CurrentBlock() + require.Equal(t, uint64(1), bl.NumberU64()) + require.Zero(gt, bl.Transactions().Len()) + + // now include the tx when we want it to + miner.ActL1StartBlock(10)(t) + miner.ActL1IncludeTx(dp.Addresses.Alice)(t) + miner.ActL1EndBlock(t) + bl = miner.l1Chain.CurrentBlock() + require.Equal(t, uint64(2), bl.NumberU64()) + require.Equal(t, 1, bl.Transactions().Len()) + require.Equal(t, tx.Hash(), bl.Transactions()[0].Hash()) + + // now make a replica that syncs these two blocks from the miner + replica := NewL1Replica(log, sd.L1Cfg) + t.Cleanup(func() { + _ = replica.Close() + }) + replica.ActL1Sync(miner.CanonL1Chain())(t) + replica.ActL1Sync(miner.CanonL1Chain())(t) + require.Equal(t, replica.l1Chain.CurrentBlock().Hash(), miner.l1Chain.CurrentBlock().Hash()) +} diff --git a/op-e2e/actions/l1_replica.go b/op-e2e/actions/l1_replica.go new file mode 100644 index 0000000000000..71c11352d6929 --- /dev/null +++ b/op-e2e/actions/l1_replica.go @@ -0,0 +1,208 @@ +package actions + +import ( + "errors" + "fmt" + + "github.com/ethereum-optimism/optimism/op-node/client" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/sources" + "github.com/ethereum-optimism/optimism/op-node/testutils" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/p2p" + "github.com/stretchr/testify/require" +) + +// L1CanonSrc is used to sync L1 from another node. +// The other node always has the canonical chain. +// May be nil if there is nothing to sync from +type L1CanonSrc func(num uint64) *types.Block + +// L1Replica is an instrumented in-memory L1 geth node that: +// - can sync from the given canonical L1 blocks source +// - can rewind the chain back (for reorgs) +// - can provide an RPC with mock errors +type L1Replica struct { + log log.Logger + + node *node.Node + eth *eth.Ethereum + + // L1 evm / chain + l1Chain *core.BlockChain + l1Database ethdb.Database + l1Cfg *core.Genesis + l1Signer types.Signer + + failL1RPC error // mock error +} + +// NewL1Replica constructs a L1Replica starting at the given genesis. +func NewL1Replica(log log.Logger, genesis *core.Genesis) *L1Replica { + ethCfg := ðconfig.Config{ + NetworkId: genesis.Config.ChainID.Uint64(), + Genesis: genesis, + RollupDisableTxPoolGossip: true, + } + nodeCfg := &node.Config{ + Name: "l1-geth", + WSHost: "127.0.0.1", + WSPort: 0, + WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, + HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, + DataDir: "", // in-memory + P2P: p2p.Config{ + NoDiscovery: true, + NoDial: true, + }, + } + n, err := node.New(nodeCfg) + if err != nil { + panic(err) + } + + backend, err := eth.New(n, ethCfg) + if err != nil { + panic(err) + } + + n.RegisterAPIs(tracers.APIs(backend.APIBackend)) + + if err := n.Start(); err != nil { + panic(fmt.Errorf("failed to start L1 geth node: %w", err)) + } + return &L1Replica{ + log: log, + node: n, + eth: backend, + l1Chain: backend.BlockChain(), + l1Database: backend.ChainDb(), + l1Cfg: genesis, + l1Signer: types.LatestSigner(genesis.Config), + failL1RPC: nil, + } +} + +// ActL1RewindToParent rewinds the L1 chain to parent block of head +func (s *L1Replica) ActL1RewindToParent(t Testing) { + s.ActL1RewindDepth(1)(t) +} + +func (s *L1Replica) ActL1RewindDepth(depth uint64) Action { + return func(t Testing) { + if depth == 0 { + return + } + head := s.l1Chain.CurrentHeader().Number.Uint64() + if head < depth { + t.InvalidAction("cannot rewind L1 past genesis (current: %d, rewind depth: %d)", head, depth) + return + } + finalized := s.l1Chain.CurrentFinalizedBlock() + if finalized != nil && head < finalized.NumberU64()+depth { + t.InvalidAction("cannot rewind head of chain past finalized block %d with rewind depth %d", finalized.NumberU64(), depth) + return + } + if err := s.l1Chain.SetHead(head - depth); err != nil { + t.Fatalf("failed to rewind L1 chain to nr %d: %v", head-depth, err) + } + } +} + +// ActL1Sync processes the next canonical L1 block, +// or rewinds one block if the canonical block cannot be applied to the head. +func (s *L1Replica) ActL1Sync(canonL1 func(num uint64) *types.Block) Action { + return func(t Testing) { + selfHead := s.l1Chain.CurrentHeader() + n := selfHead.Number.Uint64() + expected := canonL1(n) + if expected == nil || selfHead.Hash() != expected.Hash() { + s.ActL1RewindToParent(t) + return + } + next := canonL1(n + 1) + if next == nil { + t.InvalidAction("already fully synced to head %s (%d), n+1 is not there", selfHead.Hash(), n) + return + } + if next.ParentHash() != selfHead.Hash() { + // canonical chain must be set up wrong - with actions one by one it is not supposed to reorg during a single sync step. + t.Fatalf("canonical L1 source reorged unexpectedly from %s (num %d) to next block %s (parent %s)", n, selfHead.Hash(), next.Hash(), next.ParentHash()) + } + _, err := s.l1Chain.InsertChain([]*types.Block{next}) + require.NoError(t, err, "L1 replica could not sync next canonical L1 block %s (%d)", next.Hash(), next.NumberU64()) + } +} + +func (s *L1Replica) CanonL1Chain() func(num uint64) *types.Block { + return s.l1Chain.GetBlockByNumber +} + +// ActL1RPCFail makes the next L1 RPC request to this node fail +func (s *L1Replica) ActL1RPCFail(t Testing) { + if s.failL1RPC != nil { // already set to fail? + t.InvalidAction("already have a mock l1 rpc fail set") + } + s.failL1RPC = errors.New("mock L1 RPC error") +} + +func (s *L1Replica) EthClient() *ethclient.Client { + cl, _ := s.node.Attach() // never errors + return ethclient.NewClient(cl) +} + +func (s *L1Replica) RPCClient() client.RPC { + cl, _ := s.node.Attach() // never errors + return testutils.RPCErrFaker{ + RPC: client.NewBaseRPCClient(cl), + ErrFn: func() error { + err := s.failL1RPC + s.failL1RPC = nil // reset back, only error once. + return err + }, + } +} + +func (s *L1Replica) L1Client(t Testing, cfg *rollup.Config) *sources.L1Client { + l1F, err := sources.NewL1Client(s.RPCClient(), s.log, nil, sources.L1ClientDefaultConfig(cfg, false)) + require.NoError(t, err) + return l1F +} + +// ActL1FinalizeNext finalizes the next block, which must be marked as safe before doing so (see ActL1SafeNext). +func (s *L1Replica) ActL1FinalizeNext(t Testing) { + safe := s.l1Chain.CurrentSafeBlock() + finalizedNum := s.l1Chain.CurrentFinalizedBlock().NumberU64() + if safe.NumberU64() <= finalizedNum { + t.InvalidAction("need to move forward safe block before moving finalized block") + return + } + next := s.l1Chain.GetBlockByNumber(finalizedNum + 1) + if next == nil { + t.Fatalf("expected next block after finalized L1 block %d, safe head is ahead", finalizedNum) + } + s.l1Chain.SetFinalized(next) +} + +// ActL1SafeNext marks the next unsafe block as safe. +func (s *L1Replica) ActL1SafeNext(t Testing) { + safe := s.l1Chain.CurrentSafeBlock() + next := s.l1Chain.GetBlockByNumber(safe.NumberU64() + 1) + if next == nil { + t.InvalidAction("if head of chain is marked as safe then there's no next block") + return + } + s.l1Chain.SetSafe(next) +} + +func (s *L1Replica) Close() error { + return s.node.Close() +} diff --git a/op-e2e/actions/l1_replica_test.go b/op-e2e/actions/l1_replica_test.go new file mode 100644 index 0000000000000..84d37bb11da49 --- /dev/null +++ b/op-e2e/actions/l1_replica_test.go @@ -0,0 +1,111 @@ +package actions + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/beacon" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/sources" + "github.com/ethereum-optimism/optimism/op-node/testlog" +) + +var defaultRollupTestParams = &e2eutils.TestParams{ + MaxSequencerDrift: 40, + SequencerWindowSize: 120, + ChannelTimeout: 120, +} + +var defaultAlloc = &e2eutils.AllocParams{PrefundTestUsers: true} + +// Test if we can mock an RPC failure +func TestL1Replica_ActL1RPCFail(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlDebug) + replica := NewL1Replica(log, sd.L1Cfg) + t.Cleanup(func() { + _ = replica.Close() + }) + // mock an RPC failure + replica.ActL1RPCFail(t) + // check RPC failure + l1Cl, err := sources.NewL1Client(replica.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false)) + require.NoError(t, err) + _, err = l1Cl.InfoByLabel(t.Ctx(), eth.Unsafe) + require.ErrorContains(t, err, "mock") + head, err := l1Cl.InfoByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + require.Equal(gt, sd.L1Cfg.ToBlock().Hash(), head.Hash(), "expecting replica to start at genesis") +} + +// Test if we can make the replica sync an artificial L1 chain, rewind it, and reorg it +func TestL1Replica_ActL1Sync(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlDebug) + genesisBlock := sd.L1Cfg.ToBlock() + consensus := beacon.New(ethash.NewFaker()) + db := rawdb.NewMemoryDatabase() + sd.L1Cfg.MustCommit(db) + + chainA, _ := core.GenerateChain(sd.L1Cfg.Config, genesisBlock, consensus, db, 10, func(n int, g *core.BlockGen) { + g.SetCoinbase(common.Address{'A'}) + }) + chainA = append(append([]*types.Block{}, genesisBlock), chainA...) + chainB, _ := core.GenerateChain(sd.L1Cfg.Config, chainA[3], consensus, db, 10, func(n int, g *core.BlockGen) { + g.SetCoinbase(common.Address{'B'}) + }) + chainB = append(append([]*types.Block{}, chainA[:4]...), chainB...) + require.NotEqual(t, chainA[9], chainB[9], "need different chains") + canonL1 := func(blocks []*types.Block) func(num uint64) *types.Block { + return func(num uint64) *types.Block { + if num >= uint64(len(blocks)) { + return nil + } + return blocks[num] + } + } + + // Enough setup, create the test actor and run the actual actions + replica1 := NewL1Replica(log, sd.L1Cfg) + t.Cleanup(func() { + _ = replica1.Close() + }) + syncFromA := replica1.ActL1Sync(canonL1(chainA)) + // sync canonical chain A + for replica1.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainA)) { + syncFromA(t) + } + require.Equal(t, replica1.l1Chain.CurrentBlock().Hash(), chainA[len(chainA)-1].Hash(), "sync replica1 to head of chain A") + replica1.ActL1RewindToParent(t) + require.Equal(t, replica1.l1Chain.CurrentBlock().Hash(), chainA[len(chainA)-2].Hash(), "rewind replica1 to parent of chain A") + + // sync new canonical chain B + syncFromB := replica1.ActL1Sync(canonL1(chainB)) + for replica1.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainB)) { + syncFromB(t) + } + require.Equal(t, replica1.l1Chain.CurrentBlock().Hash(), chainB[len(chainB)-1].Hash(), "sync replica1 to head of chain B") + + // Adding and syncing a new replica + replica2 := NewL1Replica(log, sd.L1Cfg) + t.Cleanup(func() { + _ = replica2.Close() + }) + syncFromOther := replica2.ActL1Sync(replica1.CanonL1Chain()) + for replica2.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainB)) { + syncFromOther(t) + } + require.Equal(t, replica2.l1Chain.CurrentBlock().Hash(), chainB[len(chainB)-1].Hash(), "sync replica2 to head of chain B") +} diff --git a/op-e2e/actions/l2_engine.go b/op-e2e/actions/l2_engine.go new file mode 100644 index 0000000000000..c7401051c59d9 --- /dev/null +++ b/op-e2e/actions/l2_engine.go @@ -0,0 +1,190 @@ +package actions + +import ( + "errors" + "fmt" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/beacon" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + geth "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" + + "github.com/ethereum-optimism/optimism/op-node/client" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/sources" + "github.com/ethereum-optimism/optimism/op-node/testutils" +) + +// L2Engine is an in-memory implementation of the Engine API, +// without support for snap-sync, and no concurrency or background processes. +type L2Engine struct { + log log.Logger + + node *node.Node + eth *geth.Ethereum + + rollupGenesis *rollup.Genesis + + // L2 evm / chain + l2Chain *core.BlockChain + l2Database ethdb.Database + l2Cfg *core.Genesis + l2Signer types.Signer + + // L2 block building data + l2BuildingHeader *types.Header // block header that we add txs to for block building + l2BuildingState *state.StateDB // state used for block building + l2GasPool *core.GasPool // track gas used of ongoing building + pendingIndices map[common.Address]uint64 // per account, how many txs from the pool were already included in the block, since the pool is lagging behind block mining. + l2Transactions []*types.Transaction // collects txs that were successfully included into current block build + l2Receipts []*types.Receipt // collect receipts of ongoing building + l2ForceEmpty bool // when no additional txs may be processed (i.e. when sequencer drift runs out) + l2TxFailed []*types.Transaction // log of failed transactions which could not be included + + payloadID beacon.PayloadID // ID of payload that is currently being built + + failL2RPC error // mock error +} + +func NewL2Engine(log log.Logger, genesis *core.Genesis, rollupGenesisL1 eth.BlockID, jwtPath string) *L2Engine { + ethCfg := ðconfig.Config{ + NetworkId: genesis.Config.ChainID.Uint64(), + Genesis: genesis, + } + nodeCfg := &node.Config{ + Name: "l2-geth", + WSHost: "127.0.0.1", + WSPort: 0, + AuthAddr: "127.0.0.1", + AuthPort: 0, + WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, + HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, + JWTSecret: jwtPath, + } + n, err := node.New(nodeCfg) + if err != nil { + panic(err) + } + backend, err := geth.New(n, ethCfg) + if err != nil { + panic(err) + } + n.RegisterAPIs(tracers.APIs(backend.APIBackend)) + + chain := backend.BlockChain() + db := backend.ChainDb() + genesisBlock := chain.Genesis() + eng := &L2Engine{ + log: log, + node: n, + eth: backend, + rollupGenesis: &rollup.Genesis{ + L1: rollupGenesisL1, + L2: eth.BlockID{Hash: genesisBlock.Hash(), Number: genesisBlock.NumberU64()}, + L2Time: genesis.Timestamp, + }, + l2Chain: chain, + l2Database: db, + l2Cfg: genesis, + l2Signer: types.LatestSigner(genesis.Config), + } + // register the custom engine API, so we can serve engine requests while having more control + // over sequencing of individual txs. + n.RegisterAPIs([]rpc.API{ + { + Namespace: "engine", + Service: (*L2EngineAPI)(eng), + Authenticated: true, + }, + }) + if err := n.Start(); err != nil { + panic(fmt.Errorf("failed to start L2 op-geth node: %w", err)) + } + + return eng +} + +func (s *L2Engine) EthClient() *ethclient.Client { + cl, _ := s.node.Attach() // never errors + return ethclient.NewClient(cl) +} + +func (e *L2Engine) RPCClient() client.RPC { + cl, _ := e.node.Attach() // never errors + return testutils.RPCErrFaker{ + RPC: client.NewBaseRPCClient(cl), + ErrFn: func() error { + err := e.failL2RPC + e.failL2RPC = nil // reset back, only error once. + return err + }, + } +} + +func (e *L2Engine) EngineClient(t Testing, cfg *rollup.Config) *sources.EngineClient { + l2Cl, err := sources.NewEngineClient(e.RPCClient(), e.log, nil, sources.EngineClientDefaultConfig(cfg)) + require.NoError(t, err) + return l2Cl +} + +// ActL2RPCFail makes the next L2 RPC request fail +func (e *L2Engine) ActL2RPCFail(t Testing) { + if e.failL2RPC != nil { // already set to fail? + t.InvalidAction("already set a mock L2 rpc error") + return + } + e.failL2RPC = errors.New("mock L2 RPC error") +} + +// ActL2IncludeTx includes the next transaction from the given address in the block that is being built +func (e *L2Engine) ActL2IncludeTx(from common.Address) Action { + return func(t Testing) { + if e.l2BuildingHeader == nil { + t.InvalidAction("not currently building a block, cannot include tx from queue") + return + } + if e.l2ForceEmpty { + t.InvalidAction("cannot include any sequencer txs") + return + } + + i := e.pendingIndices[from] + txs, q := e.eth.TxPool().ContentFrom(from) + if uint64(len(txs)) <= i { + t.Fatalf("no pending txs from %s, and have %d unprocessable queued txs from this account", from, len(q)) + } + tx := txs[i] + if tx.Gas() > e.l2BuildingHeader.GasLimit { + t.Fatalf("tx consumes %d gas, more than available in L2 block %d", tx.Gas(), e.l2BuildingHeader.GasLimit) + } + if tx.Gas() > uint64(*e.l2GasPool) { + t.InvalidAction("action takes too much gas: %d, only have %d", tx.Gas(), uint64(*e.l2GasPool)) + return + } + e.pendingIndices[from] = i + 1 // won't retry the tx + receipt, err := core.ApplyTransaction(e.l2Cfg.Config, e.l2Chain, &e.l2BuildingHeader.Coinbase, + e.l2GasPool, e.l2BuildingState, e.l2BuildingHeader, tx, &e.l2BuildingHeader.GasUsed, *e.l2Chain.GetVMConfig()) + if err != nil { + e.l2TxFailed = append(e.l2TxFailed, tx) + t.Fatalf("failed to apply transaction to L1 block (tx %d): %v", len(e.l2Transactions), err) + } + e.l2Receipts = append(e.l2Receipts, receipt) + e.l2Transactions = append(e.l2Transactions, tx) + } +} + +func (e *L2Engine) Close() error { + return e.node.Close() +} diff --git a/op-e2e/actions/l2_engine_api.go b/op-e2e/actions/l2_engine_api.go new file mode 100644 index 0000000000000..d2c4432c431d0 --- /dev/null +++ b/op-e2e/actions/l2_engine_api.go @@ -0,0 +1,312 @@ +package actions + +import ( + "context" + "crypto/sha256" + "encoding/binary" + "errors" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/consensus/misc" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/trie" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/beacon" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-node/eth" +) + +// L2EngineAPI wraps an engine actor, and implements the RPC backend required to serve the engine API. +// This re-implements some of the Geth API work, but changes the API backend so we can deterministically +// build and control the L2 block contents to reach very specific edge cases as desired for testing. +type L2EngineAPI L2Engine + +var ( + STATUS_INVALID = ð.ForkchoiceUpdatedResult{PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionInvalid}, PayloadID: nil} + STATUS_SYNCING = ð.ForkchoiceUpdatedResult{PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionSyncing}, PayloadID: nil} + INVALID_TERMINAL_BLOCK = eth.PayloadStatusV1{Status: eth.ExecutionInvalid, LatestValidHash: &common.Hash{}} +) + +// computePayloadId computes a pseudo-random payloadid, based on the parameters. +func computePayloadId(headBlockHash common.Hash, params *eth.PayloadAttributes) beacon.PayloadID { + // Hash + hasher := sha256.New() + hasher.Write(headBlockHash[:]) + _ = binary.Write(hasher, binary.BigEndian, params.Timestamp) + hasher.Write(params.PrevRandao[:]) + hasher.Write(params.SuggestedFeeRecipient[:]) + for _, tx := range params.Transactions { + _ = binary.Write(hasher, binary.BigEndian, uint64(len(tx))) // length-prefix to avoid collisions + hasher.Write(tx) + } + if params.NoTxPool { + hasher.Write([]byte{1}) + } + var out beacon.PayloadID + copy(out[:], hasher.Sum(nil)[:8]) + return out +} + +func (ea *L2EngineAPI) startBlock(parent common.Hash, params *eth.PayloadAttributes) error { + if ea.l2BuildingHeader != nil { + ea.log.Warn("started building new block without ending previous block", "previous", ea.l2BuildingHeader, "prev_payload_id", ea.payloadID) + } + + parentHeader := ea.l2Chain.GetHeaderByHash(parent) + if parentHeader == nil { + return fmt.Errorf("uknown parent block: %s", parent) + } + statedb, err := state.New(parentHeader.Root, state.NewDatabase(ea.l2Database), nil) + if err != nil { + return fmt.Errorf("failed to init state db around block %s (state %s): %w", parent, parentHeader.Root, err) + } + + header := &types.Header{ + ParentHash: parent, + Coinbase: params.SuggestedFeeRecipient, + Difficulty: common.Big0, + Number: new(big.Int).Add(parentHeader.Number, common.Big1), + GasLimit: parentHeader.GasLimit, + Time: uint64(params.Timestamp), + Extra: nil, + MixDigest: common.Hash(params.PrevRandao), + } + + header.BaseFee = misc.CalcBaseFee(ea.l2Cfg.Config, parentHeader) + + ea.l2BuildingHeader = header + ea.l2BuildingState = statedb + ea.l2Receipts = make([]*types.Receipt, 0) + ea.l2Transactions = make([]*types.Transaction, 0) + ea.pendingIndices = make(map[common.Address]uint64) + ea.l2ForceEmpty = params.NoTxPool + ea.l2GasPool = new(core.GasPool).AddGas(header.GasLimit) + ea.payloadID = computePayloadId(parent, params) + + // pre-process the deposits + for i, otx := range params.Transactions { + var tx types.Transaction + if err := tx.UnmarshalBinary(otx); err != nil { + return fmt.Errorf("transaction %d is not valid: %v", i, err) + } + + receipt, err := core.ApplyTransaction(ea.l2Cfg.Config, ea.l2Chain, &ea.l2BuildingHeader.Coinbase, + ea.l2GasPool, ea.l2BuildingState, ea.l2BuildingHeader, &tx, &ea.l2BuildingHeader.GasUsed, *ea.l2Chain.GetVMConfig()) + if err != nil { + ea.l2TxFailed = append(ea.l2TxFailed, &tx) + return fmt.Errorf("failed to apply deposit transaction to L2 block (tx %d): %w", i, err) + } + ea.l2Receipts = append(ea.l2Receipts, receipt) + ea.l2Transactions = append(ea.l2Transactions, &tx) + } + return nil +} + +func (ea *L2EngineAPI) endBlock() (*types.Block, error) { + if ea.l2BuildingHeader == nil { + return nil, fmt.Errorf("no block is being built currently (id %s)", ea.payloadID) + } + header := ea.l2BuildingHeader + ea.l2BuildingHeader = nil + + header.GasUsed = header.GasLimit - uint64(*ea.l2GasPool) + header.Root = ea.l2BuildingState.IntermediateRoot(ea.l2Cfg.Config.IsEIP158(header.Number)) + block := types.NewBlock(header, ea.l2Transactions, nil, ea.l2Receipts, trie.NewStackTrie(nil)) + + // Write state changes to db + root, err := ea.l2BuildingState.Commit(ea.l2Cfg.Config.IsEIP158(header.Number)) + if err != nil { + return nil, fmt.Errorf("l2 state write error: %v", err) + } + if err := ea.l2BuildingState.Database().TrieDB().Commit(root, false, nil); err != nil { + return nil, fmt.Errorf("l2 trie write error: %v", err) + } + return block, nil +} + +func (ea *L2EngineAPI) GetPayloadV1(ctx context.Context, payloadId eth.PayloadID) (*eth.ExecutionPayload, error) { + ea.log.Trace("L2Engine API request received", "method", "GetPayload", "id", payloadId) + if ea.payloadID != payloadId { + ea.log.Warn("unexpected payload ID requested for block building", "expected", ea.payloadID, "got", payloadId) + return nil, beacon.UnknownPayload + } + bl, err := ea.endBlock() + if err != nil { + ea.log.Error("failed to finish block building", "err", err) + return nil, beacon.UnknownPayload + } + return eth.BlockAsPayload(bl) +} + +func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.ForkchoiceState, attr *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error) { + ea.log.Trace("L2Engine API request received", "method", "ForkchoiceUpdated", "head", state.HeadBlockHash, "finalized", state.FinalizedBlockHash, "safe", state.SafeBlockHash) + if state.HeadBlockHash == (common.Hash{}) { + ea.log.Warn("Forkchoice requested update to zero hash") + return STATUS_INVALID, nil + } + // Check whether we have the block yet in our database or not. If not, we'll + // need to either trigger a sync, or to reject this forkchoice update for a + // reason. + block := ea.l2Chain.GetBlockByHash(state.HeadBlockHash) + if block == nil { + // TODO: syncing not supported yet + return STATUS_SYNCING, nil + } + // Block is known locally, just sanity check that the beacon client does not + // attempt to push us back to before the merge. + if block.Difficulty().BitLen() > 0 || block.NumberU64() == 0 { + var ( + td = ea.l2Chain.GetTd(state.HeadBlockHash, block.NumberU64()) + ptd = ea.l2Chain.GetTd(block.ParentHash(), block.NumberU64()-1) + ttd = ea.l2Chain.Config().TerminalTotalDifficulty + ) + if td == nil || (block.NumberU64() > 0 && ptd == nil) { + ea.log.Error("TDs unavailable for TTD check", "number", block.NumberU64(), "hash", state.HeadBlockHash, "td", td, "parent", block.ParentHash(), "ptd", ptd) + return STATUS_INVALID, errors.New("TDs unavailable for TDD check") + } + if td.Cmp(ttd) < 0 { + ea.log.Error("Refusing beacon update to pre-merge", "number", block.NumberU64(), "hash", state.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) + return ð.ForkchoiceUpdatedResult{PayloadStatus: INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil + } + if block.NumberU64() > 0 && ptd.Cmp(ttd) >= 0 { + ea.log.Error("Parent block is already post-ttd", "number", block.NumberU64(), "hash", state.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) + return ð.ForkchoiceUpdatedResult{PayloadStatus: INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil + } + } + valid := func(id *beacon.PayloadID) *eth.ForkchoiceUpdatedResult { + return ð.ForkchoiceUpdatedResult{ + PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionValid, LatestValidHash: &state.HeadBlockHash}, + PayloadID: id, + } + } + if rawdb.ReadCanonicalHash(ea.l2Database, block.NumberU64()) != state.HeadBlockHash { + // Block is not canonical, set head. + if latestValid, err := ea.l2Chain.SetCanonical(block); err != nil { + return ð.ForkchoiceUpdatedResult{PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionInvalid, LatestValidHash: &latestValid}}, err + } + } else if ea.l2Chain.CurrentBlock().Hash() == state.HeadBlockHash { + // If the specified head matches with our local head, do nothing and keep + // generating the payload. It's a special corner case that a few slots are + // missing and we are requested to generate the payload in slot. + } else if ea.l2Chain.Config().Optimism == nil { // minor L2Engine API divergence: allow proposers to reorg their own chain + panic("engine not configured as optimism engine") + } + + // If the beacon client also advertised a finalized block, mark the local + // chain final and completely in PoS mode. + if state.FinalizedBlockHash != (common.Hash{}) { + // If the finalized block is not in our canonical tree, somethings wrong + finalBlock := ea.l2Chain.GetBlockByHash(state.FinalizedBlockHash) + if finalBlock == nil { + ea.log.Warn("Final block not available in database", "hash", state.FinalizedBlockHash) + return STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("final block not available in database")) + } else if rawdb.ReadCanonicalHash(ea.l2Database, finalBlock.NumberU64()) != state.FinalizedBlockHash { + ea.log.Warn("Final block not in canonical chain", "number", block.NumberU64(), "hash", state.HeadBlockHash) + return STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("final block not in canonical chain")) + } + // Set the finalized block + ea.l2Chain.SetFinalized(finalBlock) + } + // Check if the safe block hash is in our canonical tree, if not somethings wrong + if state.SafeBlockHash != (common.Hash{}) { + safeBlock := ea.l2Chain.GetBlockByHash(state.SafeBlockHash) + if safeBlock == nil { + ea.log.Warn("Safe block not available in database") + return STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("safe block not available in database")) + } + if rawdb.ReadCanonicalHash(ea.l2Database, safeBlock.NumberU64()) != state.SafeBlockHash { + ea.log.Warn("Safe block not in canonical chain") + return STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("safe block not in canonical chain")) + } + // Set the safe block + ea.l2Chain.SetSafe(safeBlock) + } + // If payload generation was requested, create a new block to be potentially + // sealed by the beacon client. The payload will be requested later, and we + // might replace it arbitrarily many times in between. + if attr != nil { + err := ea.startBlock(state.HeadBlockHash, attr) + if err != nil { + ea.log.Error("Failed to start block building", "err", err, "noTxPool", attr.NoTxPool, "txs", len(attr.Transactions), "timestamp", attr.Timestamp) + return STATUS_INVALID, beacon.InvalidPayloadAttributes.With(err) + } + + return valid(&ea.payloadID), nil + } + return valid(nil), nil +} + +func (ea *L2EngineAPI) NewPayloadV1(ctx context.Context, payload *eth.ExecutionPayload) (*eth.PayloadStatusV1, error) { + ea.log.Trace("L2Engine API request received", "method", "ExecutePayload", "number", payload.BlockNumber, "hash", payload.BlockHash) + txs := make([][]byte, len(payload.Transactions)) + for i, tx := range payload.Transactions { + txs[i] = tx + } + block, err := beacon.ExecutableDataToBlock(beacon.ExecutableDataV1{ + ParentHash: payload.ParentHash, + FeeRecipient: payload.FeeRecipient, + StateRoot: common.Hash(payload.StateRoot), + ReceiptsRoot: common.Hash(payload.ReceiptsRoot), + LogsBloom: payload.LogsBloom[:], + Random: common.Hash(payload.PrevRandao), + Number: uint64(payload.BlockNumber), + GasLimit: uint64(payload.GasLimit), + GasUsed: uint64(payload.GasUsed), + Timestamp: uint64(payload.Timestamp), + ExtraData: payload.ExtraData, + BaseFeePerGas: payload.BaseFeePerGas.ToBig(), + BlockHash: payload.BlockHash, + Transactions: txs, + }) + if err != nil { + log.Debug("Invalid NewPayload params", "params", payload, "error", err) + return ð.PayloadStatusV1{Status: eth.ExecutionInvalidBlockHash}, nil + } + // If we already have the block locally, ignore the entire execution and just + // return a fake success. + if block := ea.l2Chain.GetBlockByHash(payload.BlockHash); block != nil { + ea.log.Warn("Ignoring already known beacon payload", "number", payload.BlockNumber, "hash", payload.BlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) + hash := block.Hash() + return ð.PayloadStatusV1{Status: eth.ExecutionValid, LatestValidHash: &hash}, nil + } + + // TODO: skipping invalid ancestor check (i.e. not remembering previously failed blocks) + + parent := ea.l2Chain.GetBlock(block.ParentHash(), block.NumberU64()-1) + if parent == nil { + // TODO: hack, saying we accepted if we don't know the parent block. Might want to return critical error if we can't actually sync. + return ð.PayloadStatusV1{Status: eth.ExecutionAccepted, LatestValidHash: nil}, nil + } + if !ea.l2Chain.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { + ea.log.Warn("State not available, ignoring new payload") + return ð.PayloadStatusV1{Status: eth.ExecutionAccepted}, nil + } + if err := ea.l2Chain.InsertBlockWithoutSetHead(block); err != nil { + ea.log.Warn("NewPayloadV1: inserting block failed", "error", err) + // TODO not remembering the payload as invalid + return ea.invalid(err, parent.Header()), nil + } + hash := block.Hash() + return ð.PayloadStatusV1{Status: eth.ExecutionValid, LatestValidHash: &hash}, nil +} + +func (ea *L2EngineAPI) invalid(err error, latestValid *types.Header) *eth.PayloadStatusV1 { + currentHash := ea.l2Chain.CurrentBlock().Hash() + if latestValid != nil { + // Set latest valid hash to 0x0 if parent is PoW block + currentHash = common.Hash{} + if latestValid.Difficulty.BitLen() == 0 { + // Otherwise set latest valid hash to parent hash + currentHash = latestValid.Hash() + } + } + errorMsg := err.Error() + return ð.PayloadStatusV1{Status: eth.ExecutionInvalid, LatestValidHash: ¤tHash, ValidationError: &errorMsg} +} diff --git a/op-e2e/actions/l2_engine_test.go b/op-e2e/actions/l2_engine_test.go new file mode 100644 index 0000000000000..edc6a3f00a8d9 --- /dev/null +++ b/op-e2e/actions/l2_engine_test.go @@ -0,0 +1,188 @@ +package actions + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/beacon" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/sources" + "github.com/ethereum-optimism/optimism/op-node/testlog" +) + +func TestL2EngineAPI(gt *testing.T) { + t := NewDefaultTesting(gt) + jwtPath := e2eutils.WriteDefaultJWT(t) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlDebug) + genesisBlock := sd.L2Cfg.ToBlock() + consensus := beacon.New(ethash.NewFaker()) + db := rawdb.NewMemoryDatabase() + sd.L2Cfg.MustCommit(db) + + engine := NewL2Engine(log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + + l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + // build an empty block + chainA, _ := core.GenerateChain(sd.L2Cfg.Config, genesisBlock, consensus, db, 1, func(i int, gen *core.BlockGen) { + gen.SetCoinbase(common.Address{'A'}) + }) + payloadA, err := eth.BlockAsPayload(chainA[0]) + require.NoError(t, err) + + // apply the payload + status, err := l2Cl.NewPayload(t.Ctx(), payloadA) + require.NoError(t, err) + require.Equal(t, status.Status, eth.ExecutionValid) + require.Equal(t, genesisBlock.Hash(), engine.l2Chain.CurrentBlock().Hash(), "processed payloads are not immediately canonical") + + // recognize the payload as canonical + fcRes, err := l2Cl.ForkchoiceUpdate(t.Ctx(), ð.ForkchoiceState{ + HeadBlockHash: payloadA.BlockHash, + SafeBlockHash: genesisBlock.Hash(), + FinalizedBlockHash: genesisBlock.Hash(), + }, nil) + require.NoError(t, err) + require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid) + require.Equal(t, payloadA.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "now payload A is canonical") + + // build an alternative block + chainB, _ := core.GenerateChain(sd.L2Cfg.Config, genesisBlock, consensus, db, 1, func(i int, gen *core.BlockGen) { + gen.SetCoinbase(common.Address{'B'}) + }) + payloadB, err := eth.BlockAsPayload(chainB[0]) + require.NoError(t, err) + + // apply the payload + status, err = l2Cl.NewPayload(t.Ctx(), payloadB) + require.NoError(t, err) + require.Equal(t, status.Status, eth.ExecutionValid) + require.Equal(t, payloadA.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "processed payloads are not immediately canonical") + + // reorg block A in favor of block B + fcRes, err = l2Cl.ForkchoiceUpdate(t.Ctx(), ð.ForkchoiceState{ + HeadBlockHash: payloadB.BlockHash, + SafeBlockHash: genesisBlock.Hash(), + FinalizedBlockHash: genesisBlock.Hash(), + }, nil) + require.NoError(t, err) + require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid) + require.Equal(t, payloadB.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "now payload B is canonical") +} + +func TestL2EngineAPIBlockBuilding(gt *testing.T) { + t := NewDefaultTesting(gt) + jwtPath := e2eutils.WriteDefaultJWT(t) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlDebug) + genesisBlock := sd.L2Cfg.ToBlock() + db := rawdb.NewMemoryDatabase() + sd.L2Cfg.MustCommit(db) + + engine := NewL2Engine(log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + t.Cleanup(func() { + _ = engine.Close() + }) + + cl := engine.EthClient() + signer := types.LatestSigner(sd.L2Cfg.Config) + + // send a tx to the miner + tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: 0, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: new(big.Int).Add(engine.l2Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), + }) + require.NoError(gt, cl.SendTransaction(t.Ctx(), tx)) + + buildBlock := func(includeAlice bool) { + parent := engine.l2Chain.CurrentBlock() + l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + // Now let's ask the engine to build a block + fcRes, err := l2Cl.ForkchoiceUpdate(t.Ctx(), ð.ForkchoiceState{ + HeadBlockHash: parent.Hash(), + SafeBlockHash: genesisBlock.Hash(), + FinalizedBlockHash: genesisBlock.Hash(), + }, ð.PayloadAttributes{ + Timestamp: eth.Uint64Quantity(parent.Time()) + 2, + PrevRandao: eth.Bytes32{}, + SuggestedFeeRecipient: common.Address{'C'}, + Transactions: nil, + NoTxPool: false, + }) + require.NoError(t, err) + require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid) + require.NotNil(t, fcRes.PayloadID, "building a block now") + + if includeAlice { + engine.ActL2IncludeTx(dp.Addresses.Alice)(t) + } + + payload, err := l2Cl.GetPayload(t.Ctx(), *fcRes.PayloadID) + require.NoError(t, err) + require.Equal(t, parent.Hash(), payload.ParentHash, "block builds on parent block") + + // apply the payload + status, err := l2Cl.NewPayload(t.Ctx(), payload) + require.NoError(t, err) + require.Equal(t, status.Status, eth.ExecutionValid) + require.Equal(t, parent.Hash(), engine.l2Chain.CurrentBlock().Hash(), "processed payloads are not immediately canonical") + + // recognize the payload as canonical + fcRes, err = l2Cl.ForkchoiceUpdate(t.Ctx(), ð.ForkchoiceState{ + HeadBlockHash: payload.BlockHash, + SafeBlockHash: genesisBlock.Hash(), + FinalizedBlockHash: genesisBlock.Hash(), + }, nil) + require.NoError(t, err) + require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid) + require.Equal(t, payload.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "now payload is canonical") + } + buildBlock(false) + require.Zero(t, engine.l2Chain.CurrentBlock().Transactions().Len(), "no tx included") + buildBlock(true) + require.Equal(gt, 1, engine.l2Chain.CurrentBlock().Transactions().Len(), "tx from alice is included") + buildBlock(false) + require.Zero(t, engine.l2Chain.CurrentBlock().Transactions().Len(), "no tx included") + require.Equal(t, uint64(3), engine.l2Chain.CurrentBlock().NumberU64(), "built 3 blocks") +} + +func TestL2EngineAPIFail(gt *testing.T) { + t := NewDefaultTesting(gt) + jwtPath := e2eutils.WriteDefaultJWT(t) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlDebug) + engine := NewL2Engine(log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + // mock an RPC failure + engine.ActL2RPCFail(t) + // check RPC failure + l2Cl, err := sources.NewL2Client(engine.RPCClient(), log, nil, sources.L2ClientDefaultConfig(sd.RollupCfg, false)) + require.NoError(t, err) + _, err = l2Cl.InfoByLabel(t.Ctx(), eth.Unsafe) + require.ErrorContains(t, err, "mock") + head, err := l2Cl.InfoByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + require.Equal(gt, sd.L2Cfg.ToBlock().Hash(), head.Hash(), "expecting engine to start at genesis") +} diff --git a/op-e2e/actions/l2_sequencer.go b/op-e2e/actions/l2_sequencer.go new file mode 100644 index 0000000000000..753f7f064f1aa --- /dev/null +++ b/op-e2e/actions/l2_sequencer.go @@ -0,0 +1,94 @@ +package actions + +import ( + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +// L2Sequencer is an actor that functions like a rollup node, +// without the full P2P/API/Node stack, but just the derivation state, and simplified driver with sequencing ability. +type L2Sequencer struct { + L2Verifier + + sequencer *driver.Sequencer + l1OriginSelector *driver.L1OriginSelector + + seqOldOrigin bool // stay on current L1 origin when sequencing a block, unless forced to adopt the next origin + + failL2GossipUnsafeBlock error // mock error +} + +func NewL2Sequencer(log log.Logger, l1 derive.L1Fetcher, eng L2API, cfg *rollup.Config, seqConfDepth uint64) *L2Sequencer { + ver := NewL2Verifier(log, l1, eng, cfg) + return &L2Sequencer{ + L2Verifier: *ver, + sequencer: driver.NewSequencer(log, cfg, l1, eng), + l1OriginSelector: driver.NewL1OriginSelector(log, cfg, l1, seqConfDepth), + seqOldOrigin: false, + failL2GossipUnsafeBlock: nil, + } +} + +// ActL2StartBlock starts building of a new L2 block on top of the head +func (s *L2Sequencer) ActL2StartBlock(t Testing) { + if !s.l2PipelineIdle { + t.InvalidAction("cannot start L2 build when derivation is not idle") + return + } + if s.l2Building { + t.InvalidAction("already started building L2 block") + return + } + + parent := s.derivation.UnsafeL2Head() + var origin eth.L1BlockRef + if s.seqOldOrigin { + // force old origin, for testing purposes + oldOrigin, err := s.l1.L1BlockRefByHash(t.Ctx(), parent.L1Origin.Hash) + require.NoError(t, err, "failed to get current origin: %s", parent.L1Origin) + origin = oldOrigin + s.seqOldOrigin = false // don't repeat this + } else { + // select origin the real way + l1Origin, err := s.l1OriginSelector.FindL1Origin(t.Ctx(), s.l1State.L1Head(), parent) + require.NoError(t, err) + origin = l1Origin + } + + err := s.sequencer.StartBuildingBlock(t.Ctx(), parent, s.derivation.SafeL2Head().ID(), s.derivation.Finalized().ID(), origin) + require.NoError(t, err, "failed to start block building") + + s.l2Building = true +} + +// ActL2EndBlock completes a new L2 block and applies it to the L2 chain as new canonical unsafe head +func (s *L2Sequencer) ActL2EndBlock(t Testing) { + if !s.l2Building { + t.InvalidAction("cannot end L2 block building when no block is being built") + return + } + s.l2Building = false + + payload, err := s.sequencer.CompleteBuildingBlock(t.Ctx()) + // TODO: there may be legitimate temporary errors here, if we mock engine API RPC-failure. + // For advanced tests we can catch those and print a warning instead. + require.NoError(t, err) + + ref, err := derive.PayloadToBlockRef(payload, &s.rollupCfg.Genesis) + require.NoError(t, err, "payload must convert to block ref") + s.derivation.SetUnsafeHead(ref) + // TODO: action-test publishing of payload on p2p +} + +// ActL2KeepL1Origin makes the sequencer use the current L1 origin, even if the next origin is available. +func (s *L2Sequencer) ActL2KeepL1Origin(t Testing) { + if s.seqOldOrigin { // don't do this twice + t.InvalidAction("already decided to keep old L1 origin") + return + } + s.seqOldOrigin = true +} diff --git a/op-e2e/actions/l2_sequencer_test.go b/op-e2e/actions/l2_sequencer_test.go new file mode 100644 index 0000000000000..9fe2f84a763ed --- /dev/null +++ b/op-e2e/actions/l2_sequencer_test.go @@ -0,0 +1,102 @@ +package actions + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/sources" + "github.com/ethereum-optimism/optimism/op-node/testlog" +) + +func setupSequencerTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1Miner, *L2Engine, *L2Sequencer) { + jwtPath := e2eutils.WriteDefaultJWT(t) + + miner := NewL1Miner(log, sd.L1Cfg) + + l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false)) + require.NoError(t, err) + engine := NewL2Engine(log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + sequencer := NewL2Sequencer(log, l1F, l2Cl, sd.RollupCfg, 0) + return miner, engine, sequencer +} + +func TestL2Sequencer_SequencerDrift(gt *testing.T) { + t := NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, + ChannelTimeout: 20, + } + dp := e2eutils.MakeDeployParams(t, p) + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlDebug) + miner, engine, sequencer := setupSequencerTest(t, sd, log) + miner.ActL1SetFeeRecipient(common.Address{'A'}) + + sequencer.ActL2PipelineFull(t) + + signer := types.LatestSigner(sd.L2Cfg.Config) + cl := engine.EthClient() + aliceTx := func() { + n, err := cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice) + require.NoError(t, err) + tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: n, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), + }) + require.NoError(gt, cl.SendTransaction(t.Ctx(), tx)) + } + makeL2BlockWithAliceTx := func() { + aliceTx() + sequencer.ActL2StartBlock(t) + engine.ActL2IncludeTx(dp.Addresses.Alice)(t) // include a test tx from alice + sequencer.ActL2EndBlock(t) + } + + // L1 makes a block + miner.ActL1StartBlock(12)(t) + miner.ActL1EndBlock(t) + sequencer.ActL1HeadSignal(t) + origin := miner.l1Chain.CurrentBlock() + + // L2 makes blocks to catch up + for sequencer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime < origin.Time() { + makeL2BlockWithAliceTx() + require.Equal(t, uint64(0), sequencer.SyncStatus().UnsafeL2.L1Origin.Number, "no L1 origin change before time matches") + } + // Check that we adopted the origin as soon as we could (conf depth is 0) + makeL2BlockWithAliceTx() + require.Equal(t, uint64(1), sequencer.SyncStatus().UnsafeL2.L1Origin.Number, "L1 origin changes as soon as L2 time equals or exceeds L1 time") + + miner.ActL1StartBlock(12)(t) + miner.ActL1EndBlock(t) + sequencer.ActL1HeadSignal(t) + + // Make blocks up till the sequencer drift is about to surpass, but keep the old L1 origin + for sequencer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime < origin.Time()+sd.RollupCfg.MaxSequencerDrift { + sequencer.ActL2KeepL1Origin(t) + makeL2BlockWithAliceTx() + require.Equal(t, uint64(1), sequencer.SyncStatus().UnsafeL2.L1Origin.Number, "expected to keep old L1 origin") + } + + // We passed the sequencer drift: we can still keep the old origin, but can't include any txs + sequencer.ActL2KeepL1Origin(t) + sequencer.ActL2StartBlock(t) + require.True(t, engine.l2ForceEmpty, "engine should not be allowed to include anything after sequencer drift is surpassed") +} diff --git a/op-e2e/actions/l2_verifier.go b/op-e2e/actions/l2_verifier.go new file mode 100644 index 0000000000000..e8490879af2a9 --- /dev/null +++ b/op-e2e/actions/l2_verifier.go @@ -0,0 +1,202 @@ +package actions + +import ( + "context" + "errors" + "io" + + "github.com/ethereum-optimism/optimism/op-node/client" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" + "github.com/ethereum-optimism/optimism/op-node/sources" + "github.com/ethereum-optimism/optimism/op-node/testutils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + gnode "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" +) + +// L2Verifier is an actor that functions like a rollup node, +// without the full P2P/API/Node stack, but just the derivation state, and simplified driver. +type L2Verifier struct { + log log.Logger + + eng derive.Engine + + // L2 rollup + derivation *derive.DerivationPipeline + + l1 derive.L1Fetcher + l1State *driver.L1State + + l2PipelineIdle bool + l2Building bool + + rollupCfg *rollup.Config + + rpc *rpc.Server + + failRPC error // mock error +} + +type L2API interface { + derive.Engine + InfoByRpcNumber(ctx context.Context, num rpc.BlockNumber) (eth.BlockInfo, error) + // GetProof returns a proof of the account, it may return a nil result without error if the address was not found. + GetProof(ctx context.Context, address common.Address, blockTag string) (*eth.AccountResult, error) +} + +func NewL2Verifier(log log.Logger, l1 derive.L1Fetcher, eng L2API, cfg *rollup.Config) *L2Verifier { + metrics := &testutils.TestDerivationMetrics{} + pipeline := derive.NewDerivationPipeline(log, cfg, l1, eng, metrics) + pipeline.Reset() + + rollupNode := &L2Verifier{ + log: log, + eng: eng, + derivation: pipeline, + l1: l1, + l1State: driver.NewL1State(log, metrics), + l2PipelineIdle: true, + l2Building: false, + rollupCfg: cfg, + rpc: rpc.NewServer(), + } + + // setup RPC server for rollup node, hooked to the actor as backend + m := &testutils.TestRPCMetrics{} + backend := &l2VerifierBackend{verifier: rollupNode} + apis := []rpc.API{ + { + Namespace: "optimism", + Service: node.NewNodeAPI(cfg, eng, backend, log, m), + Public: true, + Authenticated: false, + }, + { + Namespace: "admin", + Version: "", + Service: node.NewAdminAPI(backend, m), + Public: true, // TODO: this field is deprecated. Do we even need this anymore? + Authenticated: false, + }, + } + if err := gnode.RegisterApis(apis, nil, rollupNode.rpc); err != nil { + panic(err) + } + return rollupNode +} + +type l2VerifierBackend struct { + verifier *L2Verifier +} + +func (s *l2VerifierBackend) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) { + return s.verifier.SyncStatus(), nil +} + +func (s *l2VerifierBackend) ResetDerivationPipeline(ctx context.Context) error { + s.verifier.derivation.Reset() + return nil +} + +func (s *L2Verifier) SyncStatus() *eth.SyncStatus { + return ð.SyncStatus{ + CurrentL1: s.derivation.Origin(), + HeadL1: s.l1State.L1Head(), + SafeL1: s.l1State.L1Safe(), + FinalizedL1: s.l1State.L1Finalized(), + UnsafeL2: s.derivation.UnsafeL2Head(), + SafeL2: s.derivation.SafeL2Head(), + FinalizedL2: s.derivation.Finalized(), + } +} + +func (s *L2Verifier) RollupClient() *sources.RollupClient { + return sources.NewRollupClient(s.RPCClient()) +} + +func (s *L2Verifier) RPCClient() client.RPC { + cl := rpc.DialInProc(s.rpc) + return testutils.RPCErrFaker{ + RPC: client.NewBaseRPCClient(cl), + ErrFn: func() error { + err := s.failRPC + s.failRPC = nil // reset back, only error once. + return err + }, + } +} + +// ActRPCFail makes the next L2 RPC request fail +func (s *L2Verifier) ActRPCFail(t Testing) { + if s.failRPC != nil { // already set to fail? + t.InvalidAction("already set a mock rpc error") + return + } + s.failRPC = errors.New("mock RPC error") +} + +func (s *L2Verifier) ActL1HeadSignal(t Testing) { + head, err := s.l1.L1BlockRefByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + s.l1State.HandleNewL1HeadBlock(head) +} + +func (s *L2Verifier) ActL1SafeSignal(t Testing) { + head, err := s.l1.L1BlockRefByLabel(t.Ctx(), eth.Safe) + require.NoError(t, err) + s.l1State.HandleNewL1SafeBlock(head) +} + +func (s *L2Verifier) ActL1FinalizedSignal(t Testing) { + head, err := s.l1.L1BlockRefByLabel(t.Ctx(), eth.Finalized) + require.NoError(t, err) + s.l1State.HandleNewL1FinalizedBlock(head) +} + +// ActL2PipelineStep runs one iteration of the L2 derivation pipeline +func (s *L2Verifier) ActL2PipelineStep(t Testing) { + if s.l2Building { + t.InvalidAction("cannot derive new data while building L2 block") + return + } + + s.l2PipelineIdle = false + err := s.derivation.Step(t.Ctx()) + if err == io.EOF { + s.l2PipelineIdle = true + return + } else if err != nil && errors.Is(err, derive.NotEnoughData) { + return + } else if err != nil && errors.Is(err, derive.ErrReset) { + s.log.Warn("Derivation pipeline is reset", "err", err) + s.derivation.Reset() + return + } else if err != nil && errors.Is(err, derive.ErrTemporary) { + s.log.Warn("Derivation process temporary error", "err", err) + return + } else if err != nil && errors.Is(err, derive.ErrCritical) { + t.Fatalf("derivation failed critically: %v", err) + } else { + return + } +} + +func (s *L2Verifier) ActL2PipelineFull(t Testing) { + s.l2PipelineIdle = false + for !s.l2PipelineIdle { + s.ActL2PipelineStep(t) + } +} + +// ActL2UnsafeGossipReceive creates an action that can receive an unsafe execution payload, like gossipsub +func (s *L2Verifier) ActL2UnsafeGossipReceive(payload *eth.ExecutionPayload) Action { + return func(t Testing) { + s.derivation.AddUnsafePayload(payload) + } +} diff --git a/op-e2e/actions/l2_verifier_test.go b/op-e2e/actions/l2_verifier_test.go new file mode 100644 index 0000000000000..d96a4c11434df --- /dev/null +++ b/op-e2e/actions/l2_verifier_test.go @@ -0,0 +1,92 @@ +package actions + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func setupVerifier(t Testing, sd *e2eutils.SetupData, log log.Logger, l1F derive.L1Fetcher) (*L2Engine, *L2Verifier) { + jwtPath := e2eutils.WriteDefaultJWT(t) + engine := NewL2Engine(log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + engCl := engine.EngineClient(t, sd.RollupCfg) + verifier := NewL2Verifier(log, l1F, engCl, sd.RollupCfg) + return engine, verifier +} + +func setupVerifierOnlyTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1Miner, *L2Engine, *L2Verifier) { + miner := NewL1Miner(log, sd.L1Cfg) + l1Cl := miner.L1Client(t, sd.RollupCfg) + engine, verifier := setupVerifier(t, sd, log, l1Cl) + return miner, engine, verifier +} + +func TestL2Verifier_SequenceWindow(gt *testing.T) { + t := NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 10, + SequencerWindowSize: 24, + ChannelTimeout: 10, + } + dp := e2eutils.MakeDeployParams(t, p) + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlDebug) + miner, engine, verifier := setupVerifierOnlyTest(t, sd, log) + miner.ActL1SetFeeRecipient(common.Address{'A'}) + + // Make two sequence windows worth of empty L1 blocks. After we pass the first sequence window, the L2 chain should get blocks + for miner.l1Chain.CurrentBlock().NumberU64() < sd.RollupCfg.SeqWindowSize*2 { + miner.ActL1StartBlock(10)(t) + miner.ActL1EndBlock(t) + + verifier.ActL2PipelineFull(t) + + l1Head := miner.l1Chain.CurrentBlock().NumberU64() + expectedL1Origin := uint64(0) + // as soon as we complete the sequence window, we force-adopt the L1 origin + if l1Head >= sd.RollupCfg.SeqWindowSize { + expectedL1Origin = l1Head - sd.RollupCfg.SeqWindowSize + 1 + } + require.Equal(t, expectedL1Origin, verifier.SyncStatus().SafeL2.L1Origin.Number, "L1 origin is forced in, given enough L1 blocks pass by") + require.LessOrEqual(t, miner.l1Chain.GetBlockByNumber(expectedL1Origin).Time(), engine.l2Chain.CurrentBlock().Time(), "L2 time higher than L1 origin time") + } + tip2N := verifier.SyncStatus() + + // Do a deep L1 reorg as deep as a sequence window, this should affect the safe L2 chain + miner.ActL1RewindDepth(sd.RollupCfg.SeqWindowSize)(t) + + // Without new L1 block, the L1 appears to not be synced, and the node shouldn't reorg + verifier.ActL2PipelineFull(t) + require.Equal(t, tip2N.SafeL2, verifier.SyncStatus().SafeL2, "still the same after verifier work") + + // Make a new empty L1 block with different data than there was before. + miner.ActL1SetFeeRecipient(common.Address{'B'}) + miner.ActL1StartBlock(10)(t) + miner.ActL1EndBlock(t) + reorgL1Block := miner.l1Chain.CurrentBlock() + + // Still no reorg, we need more L1 blocks first, before the reorged L1 block is forced in by sequence window + verifier.ActL2PipelineFull(t) + require.Equal(t, tip2N.SafeL2, verifier.SyncStatus().SafeL2) + + for miner.l1Chain.CurrentBlock().NumberU64() < sd.RollupCfg.SeqWindowSize*2 { + miner.ActL1StartBlock(10)(t) + miner.ActL1EndBlock(t) + } + + // workaround: in L1Traversal we only recognize the reorg once we see origin N+1, we don't reorg to shorter L1 chains + miner.ActL1StartBlock(10)(t) + miner.ActL1EndBlock(t) + + // Now it will reorg + verifier.ActL2PipelineFull(t) + + // due to workaround we synced one more L1 block, so we need to compare against the parent of that + got := miner.l1Chain.GetBlockByHash(miner.l1Chain.GetBlockByHash(verifier.SyncStatus().SafeL2.L1Origin.Hash).ParentHash()) + require.Equal(t, reorgL1Block.Hash(), got.Hash(), "must have reorged L2 chain to the new L1 chain") +} diff --git a/op-e2e/e2eutils/addresses.go b/op-e2e/e2eutils/addresses.go new file mode 100644 index 0000000000000..637cc4faa709b --- /dev/null +++ b/op-e2e/e2eutils/addresses.go @@ -0,0 +1,65 @@ +package e2eutils + +import ( + "bytes" + "sort" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" +) + +func collectAllocAddrs(alloc core.GenesisAlloc) []common.Address { + var out []common.Address + for addr := range alloc { + out = append(out, addr) + } + // make output deterministic + sort.Slice(out, func(i, j int) bool { + return bytes.Compare(out[i][:], out[j][:]) < 0 + }) + return out +} + +// CollectAddresses constructs a lists of addresses that may be used as fuzzing corpora +// or random address selection. +func CollectAddresses(sd *SetupData, dp *DeployParams) (out []common.Address) { + // This should be seeded with: + // - reserve 0 for selecting nil (contract creation) + out = append(out, common.Address{}) + // - zero address + out = append(out, common.Address{}) + // - addresses of signing accounts + out = append(out, dp.Addresses.All()...) + // prefunded L1/L2 accounts for testing + out = append(out, collectAllocAddrs(sd.L1Cfg.Alloc)...) + out = append(out, collectAllocAddrs(sd.L2Cfg.Alloc)...) + + // - addresses of system contracts + out = append(out, + sd.L1Cfg.Coinbase, + sd.L2Cfg.Coinbase, + sd.RollupCfg.P2PSequencerAddress, + sd.RollupCfg.FeeRecipientAddress, + sd.RollupCfg.BatchInboxAddress, + sd.RollupCfg.BatchSenderAddress, + sd.RollupCfg.DepositContractAddress, + ) + // - precompiles + for i := 0; i <= 0xff; i++ { + out = append(out, common.Address{19: byte(i)}) + } + // - masked L2 version of all the original addrs + original := out[:] + for _, addr := range original { + masked := crossdomain.ApplyL1ToL2Alias(addr) + out = append(out, masked) + } + // - unmasked L1 version of all the original addrs + for _, addr := range original { + unmasked := crossdomain.UndoL1ToL2Alias(addr) + out = append(out, unmasked) + } + return out +} diff --git a/op-e2e/e2eutils/addresses_test.go b/op-e2e/e2eutils/addresses_test.go new file mode 100644 index 0000000000000..e4a5df73bd45f --- /dev/null +++ b/op-e2e/e2eutils/addresses_test.go @@ -0,0 +1,21 @@ +package e2eutils + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCollectAddresses(t *testing.T) { + tp := &TestParams{ + MaxSequencerDrift: 40, + SequencerWindowSize: 120, + ChannelTimeout: 120, + } + dp := MakeDeployParams(t, tp) + alloc := &AllocParams{PrefundTestUsers: true} + sd := Setup(t, dp, alloc) + addrs := CollectAddresses(sd, dp) + require.NotEmpty(t, addrs) + require.Contains(t, addrs, dp.Addresses.Batcher) +} diff --git a/op-e2e/e2eutils/secrets.go b/op-e2e/e2eutils/secrets.go index 268b576aca43f..4eac6f7c1a6e4 100644 --- a/op-e2e/e2eutils/secrets.go +++ b/op-e2e/e2eutils/secrets.go @@ -15,9 +15,9 @@ import ( // We prefer a mnemonic rather than direct private keys to make it easier // to export all testing keys in external tooling for use during debugging. var DefaultMnemonicConfig = &MnemonicConfig{ - Mnemonic: "test test test test test test test test test test test junk", - Deployer: "m/44'/60'/0'/0/1", - // clique signer: removed, use engine API instead + Mnemonic: "test test test test test test test test test test test junk", + Deployer: "m/44'/60'/0'/0/1", + CliqueSigner: "m/44'/60'/0'/0/2", Proposer: "m/44'/60'/0'/0/3", Batcher: "m/44'/60'/0'/0/4", SequencerP2P: "m/44'/60'/0'/0/5", @@ -26,11 +26,13 @@ var DefaultMnemonicConfig = &MnemonicConfig{ Mallory: "m/44'/60'/0'/0/8", } -// MnemonicConfig configures the private keys for testing purposes. +// MnemonicConfig configures the private keys for the hive testnet. +// It's json-serializable, so we can ship it to e.g. the hardhat script client. type MnemonicConfig struct { Mnemonic string - Deployer string + Deployer string + CliqueSigner string // rollup actors Proposer string @@ -58,6 +60,10 @@ func (m *MnemonicConfig) Secrets() (*Secrets, error) { if err != nil { return nil, err } + cliqueSigner, err := wallet.PrivateKey(account(m.CliqueSigner)) + if err != nil { + return nil, err + } proposer, err := wallet.PrivateKey(account(m.Proposer)) if err != nil { return nil, err @@ -85,6 +91,7 @@ func (m *MnemonicConfig) Secrets() (*Secrets, error) { return &Secrets{ Deployer: deployer, + CliqueSigner: cliqueSigner, Proposer: proposer, Batcher: batcher, SequencerP2P: sequencerP2P, @@ -96,7 +103,8 @@ func (m *MnemonicConfig) Secrets() (*Secrets, error) { // Secrets bundles secp256k1 private keys for all common rollup actors for testing purposes. type Secrets struct { - Deployer *ecdsa.PrivateKey + Deployer *ecdsa.PrivateKey + CliqueSigner *ecdsa.PrivateKey // rollup actors Proposer *ecdsa.PrivateKey @@ -122,6 +130,7 @@ func EncodePrivKey(priv *ecdsa.PrivateKey) hexutil.Bytes { func (s *Secrets) Addresses() *Addresses { return &Addresses{ Deployer: crypto.PubkeyToAddress(s.Deployer.PublicKey), + CliqueSigner: crypto.PubkeyToAddress(s.CliqueSigner.PublicKey), Proposer: crypto.PubkeyToAddress(s.Proposer.PublicKey), Batcher: crypto.PubkeyToAddress(s.Batcher.PublicKey), SequencerP2P: crypto.PubkeyToAddress(s.SequencerP2P.PublicKey), @@ -133,7 +142,8 @@ func (s *Secrets) Addresses() *Addresses { // Addresses bundles the addresses for all common rollup addresses for testing purposes. type Addresses struct { - Deployer common.Address + Deployer common.Address + CliqueSigner common.Address // rollup actors Proposer common.Address @@ -148,8 +158,8 @@ type Addresses struct { func (a *Addresses) All() []common.Address { return []common.Address{ - a.Batcher, a.Deployer, + a.CliqueSigner, a.Proposer, a.Batcher, a.SequencerP2P, diff --git a/op-e2e/e2eutils/testing.go b/op-e2e/e2eutils/testing.go index 79a824f74a657..14a27a8ea9996 100644 --- a/op-e2e/e2eutils/testing.go +++ b/op-e2e/e2eutils/testing.go @@ -1,5 +1,11 @@ package e2eutils +import ( + "context" + "testing" + "time" +) + // TestingBase is an interface used for standard Go testing. // This interface is used for unit tests, benchmarks, and fuzz tests and also emulated in Hive. // @@ -24,3 +30,9 @@ type TestingBase interface { Skipped() bool TempDir() string } + +func TimeoutCtx(t *testing.T, timeout time.Duration) context.Context { + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + return ctx +} diff --git a/op-e2e/e2eutils/waits.go b/op-e2e/e2eutils/waits.go new file mode 100644 index 0000000000000..b3f8e2ab66499 --- /dev/null +++ b/op-e2e/e2eutils/waits.go @@ -0,0 +1,80 @@ +package e2eutils + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +func WaitReceiptOK(ctx context.Context, client *ethclient.Client, hash common.Hash) (*types.Receipt, error) { + return WaitReceipt(ctx, client, hash, types.ReceiptStatusSuccessful) +} + +func WaitReceiptFail(ctx context.Context, client *ethclient.Client, hash common.Hash) (*types.Receipt, error) { + return WaitReceipt(ctx, client, hash, types.ReceiptStatusFailed) +} + +func WaitReceipt(ctx context.Context, client *ethclient.Client, hash common.Hash, status uint64) (*types.Receipt, error) { + ticker := time.NewTicker(100 * time.Millisecond) + defer ticker.Stop() + for { + receipt, err := client.TransactionReceipt(ctx, hash) + if errors.Is(err, ethereum.NotFound) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-ticker.C: + continue + } + } + if err != nil { + return nil, err + } + if receipt.Status != status { + return receipt, fmt.Errorf("expected status %d, but got %d", status, receipt.Status) + } + return receipt, nil + } +} + +func WaitBlock(ctx context.Context, client *ethclient.Client, n uint64) error { + for { + height, err := client.BlockNumber(ctx) + if err != nil { + return err + } + if height < n { + time.Sleep(500 * time.Millisecond) + continue + } + break + } + + return nil +} + +func WaitFor(ctx context.Context, rate time.Duration, cb func() (bool, error)) error { + tick := time.NewTicker(rate) + defer tick.Stop() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-tick.C: + done, err := cb() + if err != nil { + return err + } + if done { + return nil + } + } + } +} diff --git a/op-e2e/geth.go b/op-e2e/geth.go index 49591241f4733..554e1c1898eb4 100644 --- a/op-e2e/geth.go +++ b/op-e2e/geth.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum/go-ethereum/cmd/utils" - rollupEth "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" @@ -23,8 +22,6 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/node" - - hdwallet "github.com/miguelmota/go-ethereum-hdwallet" ) func waitForTransaction(hash common.Hash, client *ethclient.Client, timeout time.Duration) (*types.Receipt, error) { @@ -75,36 +72,22 @@ func waitForBlock(number *big.Int, client *ethclient.Client, timeout time.Durati } } -func getGenesisInfo(client *ethclient.Client) (id rollupEth.BlockID, timestamp uint64) { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - block, err := client.BlockByNumber(ctx, common.Big0) - if err != nil { - panic(err) - } - return rollupEth.BlockID{Hash: block.Hash(), Number: block.NumberU64()}, block.Time() -} - -func initL1Geth(cfg *SystemConfig, wallet *hdwallet.Wallet, genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) { - signer := deriveAccount(wallet, cfg.CliqueSignerDerivationPath) - pk, err := wallet.PrivateKey(signer) - if err != nil { - return nil, nil, fmt.Errorf("failed to locate private key in wallet: %w", err) - } - +func initL1Geth(cfg *SystemConfig, genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) { ethConfig := ðconfig.Config{ - NetworkId: cfg.L1ChainID.Uint64(), + NetworkId: cfg.DeployConfig.L1ChainID, Genesis: genesis, } nodeConfig := &node.Config{ Name: "l1-geth", + HTTPHost: "127.0.0.1", + HTTPPort: 0, WSHost: "127.0.0.1", WSPort: 0, WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"}, HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"}, } - l1Node, l1Eth, err := createGethNode(false, nodeConfig, ethConfig, []*ecdsa.PrivateKey{pk}) + l1Node, l1Eth, err := createGethNode(false, nodeConfig, ethConfig, []*ecdsa.PrivateKey{cfg.Secrets.CliqueSigner}) if err != nil { return nil, nil, err } @@ -172,6 +155,8 @@ func initL2Geth(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath WSPort: 0, AuthAddr: "127.0.0.1", AuthPort: 0, + HTTPHost: "127.0.0.1", + HTTPPort: 0, WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"}, HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"}, JWTSecret: jwtPath, diff --git a/op-e2e/go.mod b/op-e2e/go.mod index c553a749a1be1..b916a5a7f8c6a 100644 --- a/op-e2e/go.mod +++ b/op-e2e/go.mod @@ -3,12 +3,12 @@ module github.com/ethereum-optimism/optimism/op-e2e go 1.18 require ( - github.com/ethereum-optimism/optimism/op-batcher v0.8.8 - github.com/ethereum-optimism/optimism/op-bindings v0.8.8 - github.com/ethereum-optimism/optimism/op-chain-ops v0.8.8 - github.com/ethereum-optimism/optimism/op-node v0.8.8 - github.com/ethereum-optimism/optimism/op-proposer v0.8.8 - github.com/ethereum-optimism/optimism/op-service v0.8.8 + github.com/ethereum-optimism/optimism/op-batcher v0.8.10 + github.com/ethereum-optimism/optimism/op-bindings v0.8.10 + github.com/ethereum-optimism/optimism/op-chain-ops v0.8.10 + github.com/ethereum-optimism/optimism/op-node v0.8.10 + github.com/ethereum-optimism/optimism/op-proposer v0.8.10 + github.com/ethereum-optimism/optimism/op-service v0.8.10 github.com/ethereum/go-ethereum v1.10.23 github.com/libp2p/go-libp2p v0.21.0 github.com/libp2p/go-libp2p-core v0.19.1 @@ -128,6 +128,7 @@ require ( github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect + github.com/stretchr/objx v0.4.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.5.0 // indirect diff --git a/op-e2e/go.sum b/op-e2e/go.sum index 0aa9626f4492b..f3b053a0aa914 100644 --- a/op-e2e/go.sum +++ b/op-e2e/go.sum @@ -241,18 +241,18 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd h1:NchOnosWOkH9wlix8QevGHE+6vuRa+OMGvDNsczv2kQ= github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= -github.com/ethereum-optimism/optimism/op-batcher v0.8.8 h1:raKQUL3eQtWyJ+BNYPz7IN8aWIO5Dk+XPfNXjaTUFvM= -github.com/ethereum-optimism/optimism/op-batcher v0.8.8/go.mod h1:RnDJ6ilMHfvNhKwlTt4uhxABH8dbQ8arXdZjCvUI+8A= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8 h1:HN625JI2VsRsli+U6GAXipg7lAKx8EOmGIovN79Az+I= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= -github.com/ethereum-optimism/optimism/op-chain-ops v0.8.8 h1:wNn80nhMW4srM/TvA785mikElpPJhEtTLBBuYFxjUCM= -github.com/ethereum-optimism/optimism/op-chain-ops v0.8.8/go.mod h1:l9YB+bMCfYZV6rjcC6XL0VHa+6hkgdVPioHwBL9u6r8= -github.com/ethereum-optimism/optimism/op-node v0.8.8 h1:WuZF1RsZnB+u/wwWToVaC1lZWfGfgncLusUssA3Hm+o= -github.com/ethereum-optimism/optimism/op-node v0.8.8/go.mod h1:O5nXPCx8vn9c/CHgBC7vP5utcanIQ4uhWKkJ3pAaaSQ= -github.com/ethereum-optimism/optimism/op-proposer v0.8.8 h1:IV0P64q7RJ52yvLMBLAKyqeDOxdQPGHbhmIXGkMKG/8= -github.com/ethereum-optimism/optimism/op-proposer v0.8.8/go.mod h1:PSNjVKZQxjlkDTcXnoCt3Aeo6N6nY0Ma+R+ZHOTsXU8= -github.com/ethereum-optimism/optimism/op-service v0.8.8 h1:k5E78Zr2cGU0SwjoHpFXuC1eyfXhu3oKEOnDDaFi57I= -github.com/ethereum-optimism/optimism/op-service v0.8.8/go.mod h1:K0uybOhICTc2yfhrRj0cD1m7aPkOf5C9e6bUmvf4rGA= +github.com/ethereum-optimism/optimism/op-batcher v0.8.10 h1:nnC6Xs6XH/GHb/hDN+SGzDRed+PxsImPRzk6IZKiX6o= +github.com/ethereum-optimism/optimism/op-batcher v0.8.10/go.mod h1:W7QUdBkKsDm09KVUmBSVww/DiCCglBBNuvcayWnedbc= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10 h1:aSAWCQwBQnbmv03Gvtuvn3qfTWrZu/sTlRAWrpQhiHc= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= +github.com/ethereum-optimism/optimism/op-chain-ops v0.8.10 h1:ErDuEO7Dsd7+XXlTWToBN/388IgC8eXjAPgiHoXviw4= +github.com/ethereum-optimism/optimism/op-chain-ops v0.8.10/go.mod h1:a9/PrzVU8EHKlLr6yz4YXw2VhEHYrbVogX56r26VUrY= +github.com/ethereum-optimism/optimism/op-node v0.8.10 h1:1Gc4FtR5B+HgfQ+byNn3P+tiJarpMZSYjj5iLvA3YtU= +github.com/ethereum-optimism/optimism/op-node v0.8.10/go.mod h1:6NkgIThuQbPY6fA9lI2A52DaeLM2FvrcwGCBVEY2fS8= +github.com/ethereum-optimism/optimism/op-proposer v0.8.10 h1:dLzbYmaoMBViqCPlIUFB+bagSuwsd173P8kDhUMbBTQ= +github.com/ethereum-optimism/optimism/op-proposer v0.8.10/go.mod h1:tdUw40bNis2G1uDT3jNv7BWWM+FzTar+fS5zv6o2YPA= +github.com/ethereum-optimism/optimism/op-service v0.8.10 h1:K3IABHI1b0MDrDXALvTKTbzy6IogGD6NgmbqfKEcEwM= +github.com/ethereum-optimism/optimism/op-service v0.8.10/go.mod h1:K0uybOhICTc2yfhrRj0cD1m7aPkOf5C9e6bUmvf4rGA= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= diff --git a/op-e2e/setup.go b/op-e2e/setup.go index e2ae888e2d48f..fefccb5f15469 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -2,51 +2,155 @@ package op_e2e import ( "context" + "crypto/ecdsa" "fmt" "math/big" + "os" + "path" "strings" + "testing" "time" bss "github.com/ethereum-optimism/optimism/op-batcher" - "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/metrics" rollupNode "github.com/ethereum-optimism/optimism/op-node/node" "github.com/ethereum-optimism/optimism/op-node/p2p" "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" + "github.com/ethereum-optimism/optimism/op-node/testlog" l2os "github.com/ethereum-optimism/optimism/op-proposer" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth" + geth_eth "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - hdwallet "github.com/miguelmota/go-ethereum-hdwallet" + "github.com/stretchr/testify/require" ) -// deriveAddress returns the address associated derivation path for the wallet. -// It will panic if the derivation path is not correctly formatted. -func deriveAddress(w accounts.Wallet, path string) common.Address { - return deriveAccount(w, path).Address +var ( + testingJWTSecret = [32]byte{123} +) + +func DefaultSystemConfig(t *testing.T) SystemConfig { + secrets, err := e2eutils.DefaultMnemonicConfig.Secrets() + require.NoError(t, err) + addresses := secrets.Addresses() + + return SystemConfig{ + Secrets: secrets, + + Premine: make(map[common.Address]*big.Int), + + DeployConfig: &genesis.DeployConfig{ + L1ChainID: 900, + L2ChainID: 901, + L2BlockTime: 2, + + FinalizationPeriodSeconds: 60 * 60 * 24, + MaxSequencerDrift: 10, + SequencerWindowSize: 30, + ChannelTimeout: 10, + P2PSequencerAddress: addresses.SequencerP2P, + BatchInboxAddress: common.Address{0: 0x52, 19: 0xff}, // tbd + BatchSenderAddress: addresses.Batcher, + + L2OutputOracleSubmissionInterval: 4, + L2OutputOracleStartingTimestamp: -1, + L2OutputOracleProposer: addresses.Proposer, + L2OutputOracleOwner: common.Address{}, // tbd + + L1BlockTime: 2, + L1GenesisBlockNonce: 4660, + CliqueSignerAddress: addresses.CliqueSigner, + L1GenesisBlockTimestamp: hexutil.Uint64(time.Now().Unix()), + L1GenesisBlockGasLimit: 5_000_000, + L1GenesisBlockDifficulty: uint642big(1), + L1GenesisBlockMixHash: common.Hash{}, + L1GenesisBlockCoinbase: common.Address{}, + L1GenesisBlockNumber: 0, + L1GenesisBlockGasUsed: 0, + L1GenesisBlockParentHash: common.Hash{}, + L1GenesisBlockBaseFeePerGas: uint642big(7), + + L2GenesisBlockNonce: 0, + L2GenesisBlockExtraData: []byte{}, + L2GenesisBlockGasLimit: 5_000_000, + L2GenesisBlockDifficulty: uint642big(1), + L2GenesisBlockMixHash: common.Hash{}, + L2GenesisBlockCoinbase: common.Address{0: 0x12}, + L2GenesisBlockNumber: 0, + L2GenesisBlockGasUsed: 0, + L2GenesisBlockParentHash: common.Hash{}, + L2GenesisBlockBaseFeePerGas: uint642big(7), + + OptimismBaseFeeRecipient: common.Address{0: 0x52, 19: 0xf0}, // tbd + OptimismL1FeeRecipient: common.Address{0: 0x52, 19: 0xf1}, + OptimismL2FeeRecipient: common.Address{0: 0x52, 19: 0xf2}, // tbd + L2CrossDomainMessengerOwner: common.Address{0: 0x52, 19: 0xf3}, // tbd + GasPriceOracleOwner: addresses.Alice, // tbd + GasPriceOracleOverhead: 0, + GasPriceOracleScalar: 0, + GasPriceOracleDecimals: 0, + DeploymentWaitConfirmations: 1, + + EIP1559Elasticity: 2, + EIP1559Denominator: 8, + + FundDevAccounts: true, + }, + L1InfoPredeployAddress: predeploys.L1BlockAddr, + JWTFilePath: writeDefaultJWT(t), + JWTSecret: testingJWTSecret, + Nodes: map[string]*rollupNode.Config{ + "verifier": { + Driver: driver.Config{ + VerifierConfDepth: 0, + SequencerConfDepth: 0, + SequencerEnabled: false, + }, + L1EpochPollInterval: time.Second * 4, + }, + "sequencer": { + Driver: driver.Config{ + VerifierConfDepth: 0, + SequencerConfDepth: 0, + SequencerEnabled: true, + }, + // Submitter PrivKey is set in system start for rollup nodes where sequencer = true + RPC: rollupNode.RPCConfig{ + ListenAddr: "127.0.0.1", + ListenPort: 0, + EnableAdmin: true, + }, + L1EpochPollInterval: time.Second * 4, + }, + }, + Loggers: map[string]log.Logger{ + "verifier": testlog.Logger(t, log.LvlInfo).New("role", "verifier"), + "sequencer": testlog.Logger(t, log.LvlInfo).New("role", "sequencer"), + "batcher": testlog.Logger(t, log.LvlInfo).New("role", "batcher"), + "proposer": testlog.Logger(t, log.LvlCrit).New("role", "proposer"), + }, + P2PTopology: nil, // no P2P connectivity by default + } } -// deriveAccount returns the account associated derivation path for the wallet. -// It will panic if the derivation path is not correctly formatted. -func deriveAccount(w accounts.Wallet, path string) accounts.Account { - derivPath := hdwallet.MustParseDerivationPath(path) - account, err := w.Derive(derivPath, true) - if err != nil { - panic(err) +func writeDefaultJWT(t *testing.T) string { + // Sadly the geth node config cannot load JWT secret from memory, it has to be a file + jwtPath := path.Join(t.TempDir(), "jwt_secret") + if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0600); err != nil { + t.Fatalf("failed to prepare jwt file for geth: %v", err) } - return account + return jwtPath } type L2OOContractConfig struct { @@ -60,257 +164,154 @@ type DepositContractConfig struct { } type SystemConfig struct { - Mnemonic string - Premine map[string]int // Derivation path -> amount in ETH (not wei) - CliqueSignerDerivationPath string - L2OutputHDPath string - BatchSubmitterHDPath string - P2PSignerHDPath string - DeployerHDPath string - L1InfoPredeployAddress common.Address - - L2OOCfg L2OOContractConfig - DepositCFG DepositContractConfig + Secrets *e2eutils.Secrets + L1InfoPredeployAddress common.Address - L1ChainID *big.Int - L2ChainID *big.Int + DeployConfig *genesis.DeployConfig JWTFilePath string JWTSecret [32]byte + Premine map[common.Address]*big.Int Nodes map[string]*rollupNode.Config // Per node config. Don't use populate rollup.Config Loggers map[string]log.Logger ProposerLogger log.Logger BatcherLogger log.Logger - RollupConfig rollup.Config // Shared rollup configs - - L1BlockTime uint64 // map of outbound connections to other nodes. Node names prefixed with "~" are unconnected but linked. // A nil map disables P2P completely. // Any node name not in the topology will not have p2p enabled. P2PTopology map[string][]string - - BaseFeeRecipient common.Address - L1FeeRecipient common.Address } type System struct { cfg SystemConfig - // Retain wallet - wallet *hdwallet.Wallet + RollupConfig *rollup.Config // Connections to running nodes - nodes map[string]*node.Node - backends map[string]*eth.Ethereum - Clients map[string]*ethclient.Client - RolupGenesis rollup.Genesis - rollupNodes map[string]*rollupNode.OpNode - l2OutputSubmitter *l2os.L2OutputSubmitter - batchSubmitter *bss.BatchSubmitter - L2OOContractAddr common.Address - DepositContractAddr common.Address - Mocknet mocknet.Mocknet -} - -func precompileAlloc() core.GenesisAlloc { - alloc := make(map[common.Address]core.GenesisAccount) - var addr [common.AddressLength]byte - for i := 0; i < 256; i++ { - addr[common.AddressLength-1] = byte(i) - alloc[addr] = core.GenesisAccount{Balance: common.Big1} - } - return alloc -} - -func cliqueExtraData(w accounts.Wallet, signers []string) []byte { - // 32 Empty bytes - ret := make([]byte, 32) - // Signer addresses - for _, signer := range signers { - address := deriveAddress(w, signer) - // Was not able to automatically do this - for i := 0; i < len(address); i++ { - ret = append(ret, address[i]) - } - } - // 65 Empty bytes - t := make([]byte, 65) - return append(ret, t...) + Nodes map[string]*node.Node + Backends map[string]*geth_eth.Ethereum + Clients map[string]*ethclient.Client + RollupNodes map[string]*rollupNode.OpNode + L2OutputSubmitter *l2os.L2OutputSubmitter + BatchSubmitter *bss.BatchSubmitter + Mocknet mocknet.Mocknet } func (sys *System) Close() { - if sys.l2OutputSubmitter != nil { - sys.l2OutputSubmitter.Stop() + if sys.L2OutputSubmitter != nil { + sys.L2OutputSubmitter.Stop() } - if sys.batchSubmitter != nil { - sys.batchSubmitter.Stop() + if sys.BatchSubmitter != nil { + sys.BatchSubmitter.Stop() } - for _, node := range sys.rollupNodes { + for _, node := range sys.RollupNodes { node.Close() } - for _, node := range sys.nodes { + for _, node := range sys.Nodes { node.Close() } sys.Mocknet.Close() } -func (cfg SystemConfig) start() (*System, error) { +func (cfg SystemConfig) Start() (*System, error) { sys := &System{ cfg: cfg, - nodes: make(map[string]*node.Node), - backends: make(map[string]*eth.Ethereum), + Nodes: make(map[string]*node.Node), + Backends: make(map[string]*geth_eth.Ethereum), Clients: make(map[string]*ethclient.Client), - rollupNodes: make(map[string]*rollupNode.OpNode), + RollupNodes: make(map[string]*rollupNode.OpNode), } didErrAfterStart := false defer func() { if didErrAfterStart { - for _, node := range sys.rollupNodes { + for _, node := range sys.RollupNodes { node.Close() } - for _, node := range sys.nodes { + for _, node := range sys.Nodes { node.Close() } } }() - // Wallet - wallet, err := hdwallet.NewFromMnemonic(cfg.Mnemonic) - if err != nil { - return nil, fmt.Errorf("Failed to create wallet: %w", err) - } - sys.wallet = wallet - - // Create the BSS and set it's config here because it needs to be derived from the accounts - bssPrivKey, err := wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: cfg.BatchSubmitterHDPath, - }, - }) + l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig) if err != nil { return nil, err } - batchSubmitterAddr := crypto.PubkeyToAddress(bssPrivKey.PublicKey) - p2pSignerPrivKey, err := wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: cfg.P2PSignerHDPath, - }, - }) - if err != nil { - return nil, err + for addr, amount := range cfg.Premine { + if existing, ok := l1Genesis.Alloc[addr]; ok { + l1Genesis.Alloc[addr] = core.GenesisAccount{ + Code: existing.Code, + Storage: existing.Storage, + Balance: amount, + Nonce: existing.Nonce, + } + } else { + l1Genesis.Alloc[addr] = core.GenesisAccount{ + Balance: amount, + Nonce: 0, + } + } } - p2pSignerAddr := crypto.PubkeyToAddress(p2pSignerPrivKey.PublicKey) - // Create the L2 Outputsubmitter Address and set it here because it needs to be derived from the accounts - l2OOSubmitter, err := wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: cfg.L2OutputHDPath, - }, - }) + l1Block := l1Genesis.ToBlock() + l2Addrs := &genesis.L2Addresses{ + ProxyAdmin: predeploys.DevProxyAdminAddr, + L1StandardBridgeProxy: predeploys.DevL1StandardBridgeAddr, + L1CrossDomainMessengerProxy: predeploys.DevL1CrossDomainMessengerAddr, + } + l2Genesis, err := genesis.BuildL2DeveloperGenesis(cfg.DeployConfig, l1Block, l2Addrs) if err != nil { return nil, err } - l2OutputSubmitterAddr := crypto.PubkeyToAddress(l2OOSubmitter.PublicKey) - - // Genesis - eth := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) - l1Alloc := precompileAlloc() - l2Alloc := precompileAlloc() - - for path, amt := range cfg.Premine { - balance := big.NewInt(int64(amt)) - balance.Mul(balance, eth) - addr := deriveAddress(wallet, path) - l1Alloc[addr] = core.GenesisAccount{Balance: balance} - l2Alloc[addr] = core.GenesisAccount{Balance: balance} - } - - l2Alloc[cfg.L1InfoPredeployAddress] = core.GenesisAccount{Code: common.FromHex(bindings.L1BlockDeployedBin), Balance: common.Big0} - l2Alloc[predeploys.L2ToL1MessagePasserAddr] = core.GenesisAccount{Code: common.FromHex(bindings.L2ToL1MessagePasserDeployedBin), Balance: common.Big0} - l2Alloc[predeploys.GasPriceOracleAddr] = core.GenesisAccount{Code: common.FromHex(bindings.GasPriceOracleDeployedBin), Balance: common.Big0, Storage: map[common.Hash]common.Hash{ - // storage for GasPriceOracle to have transctorPath wallet as owner - common.BigToHash(big.NewInt(0)): common.HexToHash("0x8A0A996b22B103B500Cd0F20d62dF2Ba3364D295"), - }} - - genesisTimestamp := uint64(time.Now().Unix()) - - l1Genesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: cfg.L1ChainID, - HomesteadBlock: common.Big0, - EIP150Block: common.Big0, - EIP155Block: common.Big0, - EIP158Block: common.Big0, - ByzantiumBlock: common.Big0, - ConstantinopleBlock: common.Big0, - PetersburgBlock: common.Big0, - IstanbulBlock: common.Big0, - BerlinBlock: common.Big0, - LondonBlock: common.Big0, - Clique: ¶ms.CliqueConfig{ - Period: cfg.L1BlockTime, - Epoch: 30000, - }, - }, - Alloc: l1Alloc, - Difficulty: common.Big1, - ExtraData: cliqueExtraData(wallet, []string{cfg.CliqueSignerDerivationPath}), - GasLimit: 5000000, - Nonce: 4660, - Timestamp: genesisTimestamp, - BaseFee: big.NewInt(7), - } - l2Genesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: cfg.L2ChainID, - HomesteadBlock: common.Big0, - EIP150Block: common.Big0, - EIP155Block: common.Big0, - EIP158Block: common.Big0, - ByzantiumBlock: common.Big0, - ConstantinopleBlock: common.Big0, - PetersburgBlock: common.Big0, - IstanbulBlock: common.Big0, - BerlinBlock: common.Big0, - LondonBlock: common.Big0, - MergeNetsplitBlock: common.Big0, - TerminalTotalDifficulty: common.Big0, - Optimism: ¶ms.OptimismConfig{ - BaseFeeRecipient: cfg.BaseFeeRecipient, - L1FeeRecipient: cfg.L1FeeRecipient, - EIP1559Elasticity: 2, - EIP1559Denominator: 8, + makeRollupConfig := func() rollup.Config { + return rollup.Config{ + Genesis: rollup.Genesis{ + L1: eth.BlockID{ + Hash: l1Block.Hash(), + Number: 0, + }, + L2: eth.BlockID{ + Hash: l2Genesis.ToBlock().Hash(), + Number: 0, + }, + L2Time: uint64(cfg.DeployConfig.L1GenesisBlockTimestamp), }, - }, - Alloc: l2Alloc, - Difficulty: common.Big1, - GasLimit: 5000000, - Nonce: 0, - // must be equal (or higher, while within bounds) as the L1 anchor point of the rollup - Timestamp: genesisTimestamp, - BaseFee: big.NewInt(7), + BlockTime: cfg.DeployConfig.L2BlockTime, + MaxSequencerDrift: cfg.DeployConfig.MaxSequencerDrift, + SeqWindowSize: cfg.DeployConfig.SequencerWindowSize, + ChannelTimeout: cfg.DeployConfig.ChannelTimeout, + L1ChainID: cfg.L1ChainIDBig(), + L2ChainID: cfg.L2ChainIDBig(), + P2PSequencerAddress: cfg.DeployConfig.P2PSequencerAddress, + FeeRecipientAddress: l2Genesis.Coinbase, + BatchInboxAddress: cfg.DeployConfig.BatchInboxAddress, + BatchSenderAddress: cfg.DeployConfig.BatchSenderAddress, + DepositContractAddress: predeploys.DevOptimismPortalAddr, + } } + defaultConfig := makeRollupConfig() + sys.RollupConfig = &defaultConfig // Initialize nodes - l1Node, l1Backend, err := initL1Geth(&cfg, wallet, l1Genesis) + l1Node, l1Backend, err := initL1Geth(&cfg, l1Genesis) if err != nil { return nil, err } - sys.nodes["l1"] = l1Node - sys.backends["l1"] = l1Backend + sys.Nodes["l1"] = l1Node + sys.Backends["l1"] = l1Backend for name := range cfg.Nodes { - node, backend, err := initL2Geth(name, cfg.L2ChainID, l2Genesis, cfg.JWTFilePath) + node, backend, err := initL2Geth(name, big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath) if err != nil { return nil, err } - sys.nodes[name] = node - sys.backends[name] = backend + sys.Nodes[name] = node + sys.Backends[name] = backend } // Start @@ -324,7 +325,7 @@ func (cfg SystemConfig) start() (*System, error) { didErrAfterStart = true return nil, err } - for name, node := range sys.nodes { + for name, node := range sys.Nodes { if name == "l1" { continue } @@ -337,13 +338,25 @@ func (cfg SystemConfig) start() (*System, error) { // Configure connections to L1 and L2 for rollup nodes. // TODO: refactor testing to use in-process rpc connections instead of websockets. + + l1EndpointConfig := l1Node.WSEndpoint() + useHTTP := os.Getenv("OP_E2E_USE_HTTP") == "true" + if useHTTP { + log.Info("using HTTP client") + l1EndpointConfig = l1Node.HTTPEndpoint() + } + for name, rollupCfg := range cfg.Nodes { + l2EndpointConfig := sys.Nodes[name].WSAuthEndpoint() + if useHTTP { + l2EndpointConfig = sys.Nodes[name].HTTPAuthEndpoint() + } rollupCfg.L1 = &rollupNode.L1EndpointConfig{ - L1NodeAddr: l1Node.WSEndpoint(), + L1NodeAddr: l1EndpointConfig, L1TrustRPC: false, } rollupCfg.L2 = &rollupNode.L2EndpointConfig{ - L2EngineAddr: sys.nodes[name].WSAuthEndpoint(), + L2EngineAddr: l2EndpointConfig, L2EngineJWTSecret: cfg.JWTSecret, } } @@ -358,7 +371,7 @@ func (cfg SystemConfig) start() (*System, error) { } l1Client := ethclient.NewClient(rpc.DialInProc(l1Srv)) sys.Clients["l1"] = l1Client - for name, node := range sys.nodes { + for name, node := range sys.Nodes { client, err := ethclient.DialContext(ctx, node.WSEndpoint()) if err != nil { didErrAfterStart = true @@ -367,79 +380,9 @@ func (cfg SystemConfig) start() (*System, error) { sys.Clients[name] = client } - // Rollup Genesis - l1GenesisID, _ := getGenesisInfo(l1Client) - var l2Client *ethclient.Client - for name, client := range sys.Clients { - if name != "l1" { - l2Client = client - break - } - } - l2GenesisID, l2GenesisTime := getGenesisInfo(l2Client) - - sys.RolupGenesis = rollup.Genesis{ - L1: l1GenesisID, - L2: l2GenesisID, - L2Time: l2GenesisTime, - } - - sys.cfg.RollupConfig.Genesis = sys.RolupGenesis - sys.cfg.RollupConfig.BatchSenderAddress = batchSubmitterAddr - sys.cfg.RollupConfig.P2PSequencerAddress = p2pSignerAddr - - // Deploy Deposit Contract - deployerPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: cfg.DeployerHDPath, - }, - }) + _, err = waitForBlock(big.NewInt(2), l1Client, 6*time.Second*time.Duration(cfg.DeployConfig.L1BlockTime)) if err != nil { - return nil, err - } - - opts, err := bind.NewKeyedTransactorWithChainID(deployerPrivKey, cfg.L1ChainID) - if err != nil { - return nil, err - } - - // empty genesis L2 output. - // Technically this may need to be computed with l2.ComputeL2OutputRoot(...), - // but there are no fraud proofs active in the test. - genesisL2Output := [32]byte{} - - // Deploy contracts - sys.L2OOContractAddr, _, _, err = bindings.DeployL2OutputOracle( - opts, - l1Client, - sys.cfg.L2OOCfg.SubmissionFrequency, - genesisL2Output, - sys.cfg.L2OOCfg.HistoricalTotalBlocks, - new(big.Int).SetUint64(l2GenesisID.Number), - new(big.Int).SetUint64(l2Genesis.Timestamp), - new(big.Int).SetUint64(sys.cfg.RollupConfig.BlockTime), - l2OutputSubmitterAddr, - crypto.PubkeyToAddress(deployerPrivKey.PublicKey), - ) - sys.cfg.DepositCFG.L2Oracle = sys.L2OOContractAddr - if err != nil { - return nil, err - } - var tx *types.Transaction - sys.DepositContractAddr, tx, _, err = bindings.DeployOptimismPortal( - opts, - l1Client, - sys.cfg.DepositCFG.L2Oracle, - sys.cfg.DepositCFG.FinalizationPeriod, - ) - if err != nil { - return nil, err - } - - // Wait up to 6 blocks to deploy the Optimism portal - _, err = waitForTransaction(tx.Hash(), l1Client, 6*time.Second*time.Duration(cfg.L1BlockTime)) - if err != nil { - return nil, fmt.Errorf("waiting for OptimismPortal: %w", err) + return nil, fmt.Errorf("waiting for blocks: %w", err) } sys.Mocknet = mocknet.New() @@ -496,14 +439,13 @@ func (cfg SystemConfig) start() (*System, error) { // Rollup nodes for name, nodeConfig := range cfg.Nodes { c := *nodeConfig // copy - c.Rollup = sys.cfg.RollupConfig - c.Rollup.DepositContractAddress = sys.DepositContractAddr + c.Rollup = makeRollupConfig() if p, ok := p2pNodes[name]; ok { c.P2P = p if c.Driver.SequencerEnabled { - c.P2PSigner = &p2p.PreparedSigner{Signer: p2p.NewLocalSigner(p2pSignerPrivKey)} + c.P2PSigner = &p2p.PreparedSigner{Signer: p2p.NewLocalSigner(cfg.Secrets.SequencerP2P)} } } @@ -517,7 +459,7 @@ func (cfg SystemConfig) start() (*System, error) { didErrAfterStart = true return nil, err } - sys.rollupNodes[name] = node + sys.RollupNodes[name] = node } if cfg.P2PTopology != nil { @@ -541,18 +483,12 @@ func (cfg SystemConfig) start() (*System, error) { } } - rollupEndpoint := fmt.Sprintf( - "http://%s:%d", - sys.cfg.Nodes["sequencer"].RPC.ListenAddr, - sys.cfg.Nodes["sequencer"].RPC.ListenPort, - ) - // L2Output Submitter - sys.l2OutputSubmitter, err = l2os.NewL2OutputSubmitter(l2os.Config{ - L1EthRpc: sys.nodes["l1"].WSEndpoint(), - L2EthRpc: sys.nodes["sequencer"].WSEndpoint(), - RollupRpc: rollupEndpoint, - L2OOAddress: sys.L2OOContractAddr.String(), + sys.L2OutputSubmitter, err = l2os.NewL2OutputSubmitter(l2os.Config{ + L1EthRpc: sys.Nodes["l1"].WSEndpoint(), + L2EthRpc: sys.Nodes["sequencer"].WSEndpoint(), + RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), + L2OOAddress: predeploys.DevL2OutputOracleAddr.String(), PollInterval: 50 * time.Millisecond, NumConfirmations: 1, ResubmissionTimeout: 3 * time.Second, @@ -561,25 +497,24 @@ func (cfg SystemConfig) start() (*System, error) { Level: "info", Format: "text", }, - Mnemonic: sys.cfg.Mnemonic, - L2OutputHDPath: sys.cfg.L2OutputHDPath, + PrivateKey: hexPriv(cfg.Secrets.Proposer), }, "", sys.cfg.Loggers["proposer"]) if err != nil { return nil, fmt.Errorf("unable to setup l2 output submitter: %w", err) } - if err := sys.l2OutputSubmitter.Start(); err != nil { + if err := sys.L2OutputSubmitter.Start(); err != nil { return nil, fmt.Errorf("unable to start l2 output submitter: %w", err) } // Batch Submitter - sys.batchSubmitter, err = bss.NewBatchSubmitter(bss.Config{ - L1EthRpc: sys.nodes["l1"].WSEndpoint(), - L2EthRpc: sys.nodes["sequencer"].WSEndpoint(), - RollupRpc: rollupEndpoint, + sys.BatchSubmitter, err = bss.NewBatchSubmitter(bss.Config{ + L1EthRpc: sys.Nodes["l1"].WSEndpoint(), + L2EthRpc: sys.Nodes["sequencer"].WSEndpoint(), + RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), MinL1TxSize: 1, MaxL1TxSize: 120000, - ChannelTimeout: sys.cfg.RollupConfig.ChannelTimeout, + ChannelTimeout: cfg.DeployConfig.ChannelTimeout, PollInterval: 50 * time.Millisecond, NumConfirmations: 1, ResubmissionTimeout: 5 * time.Second, @@ -588,17 +523,35 @@ func (cfg SystemConfig) start() (*System, error) { Level: "info", Format: "text", }, - Mnemonic: sys.cfg.Mnemonic, - SequencerHDPath: sys.cfg.BatchSubmitterHDPath, - SequencerBatchInboxAddress: sys.cfg.RollupConfig.BatchInboxAddress.String(), + PrivateKey: hexPriv(cfg.Secrets.Batcher), + SequencerBatchInboxAddress: cfg.DeployConfig.BatchInboxAddress.String(), }, sys.cfg.Loggers["batcher"]) if err != nil { return nil, fmt.Errorf("failed to setup batch submitter: %w", err) } - if err := sys.batchSubmitter.Start(); err != nil { + if err := sys.BatchSubmitter.Start(); err != nil { return nil, fmt.Errorf("unable to start batch submitter: %w", err) } return sys, nil } + +func (cfg SystemConfig) L1ChainIDBig() *big.Int { + return new(big.Int).SetUint64(cfg.DeployConfig.L1ChainID) +} + +func (cfg SystemConfig) L2ChainIDBig() *big.Int { + return new(big.Int).SetUint64(cfg.DeployConfig.L2ChainID) +} + +func uint642big(in uint64) *hexutil.Big { + b := new(big.Int).SetUint64(in) + hu := hexutil.Big(*b) + return &hu +} + +func hexPriv(in *ecdsa.PrivateKey) string { + b := e2eutils.EncodePrivKey(in) + return hexutil.Encode(b) +} diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index 07569143de0aa..ea00a970972fa 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -5,28 +5,21 @@ import ( "flag" "fmt" "math/big" - "os" - "path" "testing" "time" "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/eth" - "github.com/ethereum-optimism/optimism/op-node/node" - rollupNode "github.com/ethereum-optimism/optimism/op-node/node" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/sources" "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" @@ -49,129 +42,26 @@ func init() { flag.Parse() } -// Temporary until the contract is deployed properly instead of as a pre-deploy to a specific address -var MockDepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") - -const ( - cliqueSignerHDPath = "m/44'/60'/0'/0/0" - transactorHDPath = "m/44'/60'/0'/0/1" - l2OutputHDPath = "m/44'/60'/0'/0/3" - bssHDPath = "m/44'/60'/0'/0/4" - p2pSignerHDPath = "m/44'/60'/0'/0/5" - deployerHDPath = "m/44'/60'/0'/0/6" -) - -var ( - batchInboxAddress = common.Address{0xff, 0x02} - testingJWTSecret = [32]byte{123} -) - -func writeDefaultJWT(t *testing.T) string { - // Sadly the geth node config cannot load JWT secret from memory, it has to be a file - jwtPath := path.Join(t.TempDir(), "jwt_secret") - if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0600); err != nil { - t.Fatalf("failed to prepare jwt file for geth: %v", err) - } - return jwtPath -} - -func defaultSystemConfig(t *testing.T) SystemConfig { - return SystemConfig{ - Mnemonic: "squirrel green gallery layer logic title habit chase clog actress language enrich body plate fun pledge gap abuse mansion define either blast alien witness", - Premine: map[string]int{ - cliqueSignerHDPath: 10000000, - transactorHDPath: 10000000, - l2OutputHDPath: 10000000, - bssHDPath: 10000000, - deployerHDPath: 10000000, - }, - DepositCFG: DepositContractConfig{ - FinalizationPeriod: big.NewInt(60 * 60 * 24), - }, - L2OOCfg: L2OOContractConfig{ - SubmissionFrequency: big.NewInt(4), - HistoricalTotalBlocks: big.NewInt(0), - }, - L2OutputHDPath: l2OutputHDPath, - BatchSubmitterHDPath: bssHDPath, - P2PSignerHDPath: p2pSignerHDPath, - DeployerHDPath: deployerHDPath, - CliqueSignerDerivationPath: cliqueSignerHDPath, - L1InfoPredeployAddress: predeploys.L1BlockAddr, - L1BlockTime: 2, - L1ChainID: big.NewInt(900), - L2ChainID: big.NewInt(901), - JWTFilePath: writeDefaultJWT(t), - JWTSecret: testingJWTSecret, - Nodes: map[string]*rollupNode.Config{ - "verifier": { - Driver: driver.Config{ - VerifierConfDepth: 0, - SequencerConfDepth: 0, - SequencerEnabled: false, - }, - L1EpochPollInterval: time.Second * 4, - }, - "sequencer": { - Driver: driver.Config{ - VerifierConfDepth: 0, - SequencerConfDepth: 0, - SequencerEnabled: true, - }, - // Submitter PrivKey is set in system start for rollup nodes where sequencer = true - RPC: node.RPCConfig{ - ListenAddr: "127.0.0.1", - ListenPort: 9093, - EnableAdmin: true, - }, - L1EpochPollInterval: time.Second * 4, - }, - }, - Loggers: map[string]log.Logger{ - "verifier": testlog.Logger(t, log.LvlInfo).New("role", "verifier"), - "sequencer": testlog.Logger(t, log.LvlInfo).New("role", "sequencer"), - "batcher": testlog.Logger(t, log.LvlInfo).New("role", "batcher"), - "proposer": testlog.Logger(t, log.LvlCrit).New("role", "proposer"), - }, - RollupConfig: rollup.Config{ - BlockTime: 1, - MaxSequencerDrift: 10, - SeqWindowSize: 30, - ChannelTimeout: 10, - L1ChainID: big.NewInt(900), - L2ChainID: big.NewInt(901), - // TODO pick defaults - P2PSequencerAddress: common.Address{}, // TODO configure sequencer p2p key - FeeRecipientAddress: common.Address{0xff, 0x01}, - BatchInboxAddress: batchInboxAddress, - // Batch Sender address is filled out in system start - DepositContractAddress: MockDepositContractAddr, - }, - P2PTopology: nil, // no P2P connectivity by default - BaseFeeRecipient: common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"), - L1FeeRecipient: common.HexToAddress("0xDe3829A23DF1479438622a08a116E8Eb3f620BB5"), - } -} - func TestL2OutputSubmitter(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } - cfg := defaultSystemConfig(t) + cfg := DefaultSystemConfig(t) - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() l1Client := sys.Clients["l1"] - rollupRPCClient, err := rpc.DialContext(context.Background(), cfg.Nodes["sequencer"].RPC.HttpEndpoint()) + rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint()) require.Nil(t, err) - rollupClient := sources.NewRollupClient(rollupRPCClient) + rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient)) // OutputOracle is already deployed - l2OutputOracle, err := bindings.NewL2OutputOracleCaller(sys.L2OOContractAddr, l1Client) + l2OutputOracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client) require.Nil(t, err) initialOutputBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) @@ -183,7 +73,7 @@ func TestL2OutputSubmitter(t *testing.T) { // for that block and subsequently reorgs to match what the verifier derives when running the // reconcillation process. l2Verif := sys.Clients["verifier"] - _, err = waitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.RollupConfig.BlockTime)*time.Second) + _, err = waitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.Nil(t, err) // Wait for batch submitter to update L2 output oracle. @@ -223,48 +113,41 @@ func TestL2OutputSubmitter(t *testing.T) { case <-ticker.C: } } - } // TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. // All nodes are run in process (but are the full nodes, not mocked or stubbed). func TestSystemE2E(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } - cfg := defaultSystemConfig(t) + cfg := DefaultSystemConfig(t) - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() log := testlog.Logger(t, log.LvlInfo) - log.Info("genesis", "l2", sys.cfg.RollupConfig.Genesis.L2, "l1", sys.cfg.RollupConfig.Genesis.L1, "l2_time", sys.cfg.RollupConfig.Genesis.L2Time) + log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) l1Client := sys.Clients["l1"] l2Seq := sys.Clients["sequencer"] l2Verif := sys.Clients["verifier"] // Transactor Account - ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: "m/44'/60'/0'/0/0", - }, - }) - require.Nil(t, err) + ethPrivKey := sys.cfg.Secrets.Alice // Send Transaction & wait for success - fromAddr := common.HexToAddress("0x30ec912c5b1d14aa6d1cb9aa7a6682415c4f7eb0") + fromAddr := sys.cfg.Secrets.Addresses().Alice // Find deposit contract - depositContract, err := bindings.NewOptimismPortal(sys.DepositContractAddr, l1Client) + depositContract, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) require.Nil(t, err) - l1Node := sys.nodes["l1"] // Create signer - ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], cfg.L1ChainID) + opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) require.Nil(t, err) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) @@ -278,13 +161,13 @@ func TestSystemE2E(t *testing.T) { tx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, 1_000_000, false, nil) require.Nil(t, err, "with deposit tx") - receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for deposit tx on L1") reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0]) require.NoError(t, err, "Could not reconstruct L2 Deposit") tx = types.NewTx(reconstructedDep) - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.NoError(t, err) require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) @@ -296,12 +179,12 @@ func TestSystemE2E(t *testing.T) { diff := new(big.Int) diff = diff.Sub(endBalance, startBalance) - require.Equal(t, diff, mintAmount, "Did not get expected balance change") + require.Equal(t, mintAmount, diff, "Did not get expected balance change") // Submit TX to L2 sequencer node toAddr := common.Address{0xff, 0xff} - tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{ - ChainID: cfg.L2ChainID, + tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ + ChainID: cfg.L2ChainIDBig(), Nonce: 1, // Already have deposit To: &toAddr, Value: big.NewInt(1_000_000_000), @@ -312,10 +195,10 @@ func TestSystemE2E(t *testing.T) { err = l2Seq.SendTransaction(context.Background(), tx) require.Nil(t, err, "Sending L2 tx to sequencer") - _, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second) + _, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on sequencer") - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on verifier") require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "TX should have succeeded") @@ -328,9 +211,9 @@ func TestSystemE2E(t *testing.T) { require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx") require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx") - rollupRPCClient, err := rpc.DialContext(context.Background(), cfg.Nodes["sequencer"].RPC.HttpEndpoint()) + rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint()) require.Nil(t, err) - rollupClient := sources.NewRollupClient(rollupRPCClient) + rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient)) // basic check that sync status works seqStatus, err := rollupClient.SyncStatus(context.Background()) require.Nil(t, err) @@ -343,25 +226,26 @@ func TestSystemE2E(t *testing.T) { // TestConfirmationDepth runs the rollup with both sequencer and verifier not immediately processing the tip of the chain. func TestConfirmationDepth(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } - cfg := defaultSystemConfig(t) - cfg.RollupConfig.SeqWindowSize = 4 - cfg.RollupConfig.MaxSequencerDrift = 3 * cfg.L1BlockTime + cfg := DefaultSystemConfig(t) + cfg.DeployConfig.SequencerWindowSize = 4 + cfg.DeployConfig.MaxSequencerDrift = 3 * cfg.DeployConfig.L1BlockTime seqConfDepth := uint64(2) verConfDepth := uint64(5) cfg.Nodes["sequencer"].Driver.SequencerConfDepth = seqConfDepth cfg.Nodes["sequencer"].Driver.VerifierConfDepth = 0 cfg.Nodes["verifier"].Driver.VerifierConfDepth = verConfDepth - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() log := testlog.Logger(t, log.LvlInfo) - log.Info("genesis", "l2", sys.cfg.RollupConfig.Genesis.L2, "l1", sys.cfg.RollupConfig.Genesis.L1, "l2_time", sys.cfg.RollupConfig.Genesis.L2Time) + log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) l1Client := sys.Clients["l1"] l2Seq := sys.Clients["sequencer"] @@ -369,7 +253,7 @@ func TestConfirmationDepth(t *testing.T) { // Wait enough time for the sequencer to submit a block with distance from L1 head, submit it, // and for the slower verifier to read a full sequence window and cover confirmation depth for reading and some margin - <-time.After(time.Duration((cfg.RollupConfig.SeqWindowSize+verConfDepth+3)*cfg.L1BlockTime) * time.Second) + <-time.After(time.Duration((cfg.DeployConfig.SequencerWindowSize+verConfDepth+3)*cfg.DeployConfig.L1BlockTime) * time.Second) // within a second, get both L1 and L2 verifier and sequencer block heads ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) @@ -385,18 +269,19 @@ func TestConfirmationDepth(t *testing.T) { require.NoError(t, err) require.LessOrEqual(t, info.Number+seqConfDepth, l1Head.NumberU64(), "the L2 head block should have an origin older than the L1 head block by at least the sequencer conf depth") - require.LessOrEqual(t, l2VerHead.Time()+cfg.L1BlockTime*verConfDepth, l2SeqHead.Time(), "the L2 verifier head should lag behind the sequencer without delay by at least the verifier conf depth") + require.LessOrEqual(t, l2VerHead.Time()+cfg.DeployConfig.L1BlockTime*verConfDepth, l2SeqHead.Time(), "the L2 verifier head should lag behind the sequencer without delay by at least the verifier conf depth") } // TestFinalize tests if L2 finalizes after sufficient time after L1 finalizes func TestFinalize(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } - cfg := defaultSystemConfig(t) + cfg := DefaultSystemConfig(t) - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() @@ -405,7 +290,7 @@ func TestFinalize(t *testing.T) { // as configured in the extra geth lifecycle in testing setup finalizedDistance := uint64(8) // Wait enough time for L1 to finalize and L2 to confirm its data in finalized L1 blocks - <-time.After(time.Duration((finalizedDistance+4)*cfg.L1BlockTime) * time.Second) + <-time.After(time.Duration((finalizedDistance+4)*cfg.DeployConfig.L1BlockTime) * time.Second) // fetch the finalizes head of geth ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) @@ -417,12 +302,13 @@ func TestFinalize(t *testing.T) { } func TestMintOnRevertedDeposit(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } - cfg := defaultSystemConfig(t) + cfg := DefaultSystemConfig(t) - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() @@ -430,13 +316,13 @@ func TestMintOnRevertedDeposit(t *testing.T) { l2Verif := sys.Clients["verifier"] // Find deposit contract - depositContract, err := bindings.NewOptimismPortal(sys.DepositContractAddr, l1Client) + depositContract, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) require.Nil(t, err) - l1Node := sys.nodes["l1"] + l1Node := sys.Nodes["l1"] // create signer ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], cfg.L1ChainID) + opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], cfg.L1ChainIDBig()) require.Nil(t, err) fromAddr := opts.From @@ -457,13 +343,13 @@ func TestMintOnRevertedDeposit(t *testing.T) { tx, err := depositContract.DepositTransaction(opts, toAddr, value, 1_000_000, false, nil) require.Nil(t, err, "with deposit tx") - receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for deposit tx on L1") reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0]) require.NoError(t, err, "Could not reconstruct L2 Deposit") tx = types.NewTx(reconstructedDep) - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.NoError(t, err) require.Equal(t, receipt.Status, types.ReceiptStatusFailed) @@ -490,6 +376,7 @@ func TestMintOnRevertedDeposit(t *testing.T) { } func TestMissingBatchE2E(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -497,14 +384,14 @@ func TestMissingBatchE2E(t *testing.T) { // The test logs may look scary, but this is expected: // 'batcher unable to publish transaction role=batcher err="insufficient funds for gas * price + value"' - cfg := defaultSystemConfig(t) + cfg := DefaultSystemConfig(t) // small sequence window size so the test does not take as long - cfg.RollupConfig.SeqWindowSize = 4 + cfg.DeployConfig.SequencerWindowSize = 4 // Specifically set batch submitter balance to stop batches from being included - cfg.Premine[bssHDPath] = 0 + cfg.Premine[cfg.Secrets.Addresses().Batcher] = big.NewInt(0) - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() @@ -512,17 +399,12 @@ func TestMissingBatchE2E(t *testing.T) { l2Verif := sys.Clients["verifier"] // Transactor Account - ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: transactorHDPath, - }, - }) - require.Nil(t, err) + ethPrivKey := cfg.Secrets.Alice // Submit TX to L2 sequencer node toAddr := common.Address{0xff, 0xff} - tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{ - ChainID: cfg.L2ChainID, + tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ + ChainID: cfg.L2ChainIDBig(), Nonce: 0, To: &toAddr, Value: big.NewInt(1_000_000_000), @@ -534,11 +416,11 @@ func TestMissingBatchE2E(t *testing.T) { require.Nil(t, err, "Sending L2 tx to sequencer") // Let it show up on the unsafe chain - receipt, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on sequencer") // Wait until the block it was first included in shows up in the safe chain on the verifier - _, err = waitForBlock(receipt.BlockNumber, l2Verif, time.Duration(cfg.RollupConfig.SeqWindowSize*cfg.L1BlockTime)*time.Second) + _, err = waitForBlock(receipt.BlockNumber, l2Verif, time.Duration(sys.RollupConfig.SeqWindowSize*cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for block on verifier") // Assert that the transaction is not found on the verifier @@ -599,14 +481,15 @@ func L1InfoFromState(ctx context.Context, contract *bindings.L1Block, l2Number * // TestSystemMockP2P sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that // the nodes can sync L2 blocks before they are confirmed on L1. func TestSystemMockP2P(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } - cfg := defaultSystemConfig(t) + cfg := DefaultSystemConfig(t) // slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do. // Keep the seq window small so the L2 chain is started quick - cfg.L1BlockTime = 10 + cfg.DeployConfig.L1BlockTime = 10 // connect the nodes cfg.P2PTopology = map[string][]string{ @@ -624,7 +507,7 @@ func TestSystemMockP2P(t *testing.T) { cfg.Nodes["sequencer"].Tracer = seqTracer cfg.Nodes["verifier"].Tracer = verifTracer - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() @@ -632,17 +515,12 @@ func TestSystemMockP2P(t *testing.T) { l2Verif := sys.Clients["verifier"] // Transactor Account - ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: transactorHDPath, - }, - }) - require.Nil(t, err) + ethPrivKey := cfg.Secrets.Alice // Submit TX to L2 sequencer node toAddr := common.Address{0xff, 0xff} - tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{ - ChainID: cfg.L2ChainID, + tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ + ChainID: cfg.L2ChainIDBig(), Nonce: 0, To: &toAddr, Value: big.NewInt(1_000_000_000), @@ -654,11 +532,11 @@ func TestSystemMockP2P(t *testing.T) { require.Nil(t, err, "Sending L2 tx to sequencer") // Wait for tx to be mined on the L2 sequencer chain - receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.RollupConfig.BlockTime)*time.Second) + receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on sequencer") // Wait until the block it was first included in shows up in the safe chain on the verifier - receiptVerif, err := waitForTransaction(tx.Hash(), l2Verif, 6*time.Duration(cfg.RollupConfig.BlockTime)*time.Second) + receiptVerif, err := waitForTransaction(tx.Hash(), l2Verif, 6*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on verifier") require.Equal(t, receiptSeq, receiptVerif) @@ -672,13 +550,14 @@ func TestSystemMockP2P(t *testing.T) { } func TestL1InfoContract(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } - cfg := defaultSystemConfig(t) + cfg := DefaultSystemConfig(t) - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() @@ -795,14 +674,15 @@ func calcL1GasUsed(data []byte, overhead *big.Int) *big.Int { // balance changes on L1 and L2 and has to include gas fees in the balance checks. // It does not check that the withdrawal can be executed prior to the end of the finality period. func TestWithdrawals(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } - cfg := defaultSystemConfig(t) - cfg.DepositCFG.FinalizationPeriod = big.NewInt(2) // 2s finalization period + cfg := DefaultSystemConfig(t) + cfg.DeployConfig.FinalizationPeriodSeconds = 2 // 2s finalization period - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() @@ -811,20 +691,15 @@ func TestWithdrawals(t *testing.T) { l2Verif := sys.Clients["verifier"] // Transactor Account - ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: transactorHDPath, - }, - }) - require.Nil(t, err) + ethPrivKey := cfg.Secrets.Alice fromAddr := crypto.PubkeyToAddress(ethPrivKey.PublicKey) // Find deposit contract - depositContract, err := bindings.NewOptimismPortal(sys.DepositContractAddr, l1Client) + depositContract, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) require.Nil(t, err) // Create L1 signer - opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainID) + opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) require.Nil(t, err) // Start L2 balance @@ -839,7 +714,7 @@ func TestWithdrawals(t *testing.T) { tx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, 1_000_000, false, nil) require.Nil(t, err, "with deposit tx") - receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for deposit tx on L1") // Bind L2 Withdrawer Contract @@ -850,7 +725,7 @@ func TestWithdrawals(t *testing.T) { reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0]) require.NoError(t, err, "Could not reconstruct L2 Deposit") tx = types.NewTx(reconstructedDep) - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.NoError(t, err) require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) @@ -872,13 +747,13 @@ func TestWithdrawals(t *testing.T) { // Intiate Withdrawal withdrawAmount := big.NewInt(500_000_000_000) - l2opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L2ChainID) + l2opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L2ChainIDBig()) require.Nil(t, err) l2opts.Value = withdrawAmount tx, err = l2withdrawer.InitiateWithdrawal(l2opts, fromAddr, big.NewInt(21000), nil) require.Nil(t, err, "sending initiate withdraw tx") - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "withdrawal initiated on L2 sequencer") require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") @@ -906,9 +781,9 @@ func TestWithdrawals(t *testing.T) { require.Nil(t, err) // Wait for finalization and then create the Finalized Withdrawal Transaction - ctx, cancel = context.WithTimeout(context.Background(), 20*time.Duration(cfg.L1BlockTime)*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 20*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) defer cancel() - blockNumber, err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, sys.DepositContractAddr, receipt.BlockNumber) + blockNumber, err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, predeploys.DevOptimismPortalAddr, receipt.BlockNumber) require.Nil(t, err) ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) @@ -916,7 +791,7 @@ func TestWithdrawals(t *testing.T) { header, err = l2Verif.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNumber)) require.Nil(t, err) - rpc, err := rpc.Dial(sys.nodes["verifier"].WSEndpoint()) + rpc, err := rpc.Dial(sys.Nodes["verifier"].WSEndpoint()) require.Nil(t, err) l2client := withdrawals.NewClient(rpc) @@ -924,7 +799,7 @@ func TestWithdrawals(t *testing.T) { params, err := withdrawals.FinalizeWithdrawalParameters(context.Background(), l2client, tx.Hash(), header) require.Nil(t, err) - portal, err := bindings.NewOptimismPortal(sys.DepositContractAddr, l1Client) + portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) require.Nil(t, err) opts.Value = nil @@ -945,7 +820,7 @@ func TestWithdrawals(t *testing.T) { require.Nil(t, err) - receipt, err = waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "finalize withdrawal") require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) @@ -970,13 +845,14 @@ func TestWithdrawals(t *testing.T) { // TestFees checks that L1/L2 fees are handled. func TestFees(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } - cfg := defaultSystemConfig(t) + cfg := DefaultSystemConfig(t) - sys, err := cfg.start() + sys, err := cfg.Start() require.Nil(t, err, "Error starting up system") defer sys.Close() @@ -984,12 +860,7 @@ func TestFees(t *testing.T) { l2Verif := sys.Clients["verifier"] // Transactor Account - ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: transactorHDPath, - }, - }) - require.Nil(t, err) + ethPrivKey := cfg.Secrets.Alice fromAddr := crypto.PubkeyToAddress(ethPrivKey.PublicKey) // Find gaspriceoracle contract @@ -997,14 +868,14 @@ func TestFees(t *testing.T) { require.Nil(t, err) // GPO signer - l2opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L2ChainID) + l2opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L2ChainIDBig()) require.Nil(t, err) // Update overhead tx, err := gpoContract.SetOverhead(l2opts, big.NewInt(2100)) require.Nil(t, err, "sending overhead update tx") - receipt, err := waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err := waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "waiting for overhead update tx") require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") @@ -1012,7 +883,7 @@ func TestFees(t *testing.T) { tx, err = gpoContract.SetDecimals(l2opts, big.NewInt(6)) require.Nil(t, err, "sending gpo update tx") - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "waiting for gpo decimals update tx") require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") @@ -1020,7 +891,7 @@ func TestFees(t *testing.T) { tx, err = gpoContract.SetScalar(l2opts, big.NewInt(1_000_000)) require.Nil(t, err, "sending gpo update tx") - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "waiting for gpo scalar update tx") require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") @@ -1038,13 +909,13 @@ func TestFees(t *testing.T) { // BaseFee Recipient ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() - baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.BaseFeeRecipient, nil) + baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismBaseFeeRecipient, nil) require.Nil(t, err) // L1Fee Recipient ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) defer cancel() - l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.L1FeeRecipient, nil) + l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL2FeeRecipient, nil) require.Nil(t, err) // Simple transfer from signer to random account @@ -1056,8 +927,8 @@ func TestFees(t *testing.T) { toAddr := common.Address{0xff, 0xff} transferAmount := big.NewInt(1_000_000_000) gasTip := big.NewInt(10) - tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{ - ChainID: cfg.L2ChainID, + tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ + ChainID: cfg.L2ChainIDBig(), Nonce: 3, // Already have deposit To: &toAddr, Value: transferAmount, @@ -1068,10 +939,10 @@ func TestFees(t *testing.T) { err = l2Seq.SendTransaction(context.Background(), tx) require.Nil(t, err, "Sending L2 tx to sequencer") - _, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second) + _, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on sequencer") - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on verifier") require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "TX should have succeeded") @@ -1097,7 +968,7 @@ func TestFees(t *testing.T) { ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) defer cancel() - baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.BaseFeeRecipient, header.Number) + baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismBaseFeeRecipient, header.Number) require.Nil(t, err) l1Header, err := sys.Clients["l1"].HeaderByNumber(ctx, nil) @@ -1105,7 +976,7 @@ func TestFees(t *testing.T) { ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) defer cancel() - l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.L1FeeRecipient, nil) + l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL2FeeRecipient, nil) require.Nil(t, err) // Diff fee recipient + coinbase balances diff --git a/op-node/client/polling.go b/op-node/client/polling.go new file mode 100644 index 0000000000000..637371477cc69 --- /dev/null +++ b/op-node/client/polling.go @@ -0,0 +1,195 @@ +package client + +import ( + "context" + "errors" + "sync" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" +) + +var ErrSubscriberClosed = errors.New("subscriber closed") + +// PollingClient is an RPC client that provides newHeads subscriptions +// via a polling loop. It's designed for HTTP endpoints, but WS will +// work too. +type PollingClient struct { + c RPC + lgr log.Logger + pollRate time.Duration + ctx context.Context + cancel context.CancelFunc + currHead *types.Header + subID int + + // pollReqCh is used to request new polls of the upstream + // RPC client. + pollReqCh chan struct{} + + mtx sync.RWMutex + + subs map[int]chan *types.Header + + closedCh chan struct{} +} + +type WrappedHTTPClientOption func(w *PollingClient) + +// WithPollRate specifies the rate at which the PollingClient will poll +// for new heads. Setting this to zero disables polling altogether, +// which is useful for testing. +func WithPollRate(duration time.Duration) WrappedHTTPClientOption { + return func(w *PollingClient) { + w.pollRate = duration + } +} + +// NewPollingClient returns a new PollingClient. Canceling the passed-in context +// will close the client. Callers are responsible for closing the client in order +// to prevent resource leaks. +func NewPollingClient(ctx context.Context, lgr log.Logger, c RPC, opts ...WrappedHTTPClientOption) *PollingClient { + ctx, cancel := context.WithCancel(ctx) + res := &PollingClient{ + c: c, + lgr: lgr, + pollRate: 250 * time.Millisecond, + ctx: ctx, + cancel: cancel, + pollReqCh: make(chan struct{}, 1), + subs: make(map[int]chan *types.Header), + closedCh: make(chan struct{}), + } + for _, opt := range opts { + opt(res) + } + go res.pollHeads() + return res +} + +// Close closes the PollingClient and the underlying RPC client it talks to. +func (w *PollingClient) Close() { + w.cancel() + <-w.closedCh + w.c.Close() +} + +func (w *PollingClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + return w.c.CallContext(ctx, result, method, args...) +} + +func (w *PollingClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + return w.c.BatchCallContext(ctx, b) +} + +// EthSubscribe creates a new newHeads subscription. It takes identical arguments +// to Geth's native EthSubscribe method. It will return an error, however, if the +// passed in channel is not a *types.Headers channel or the subscription type is not +// newHeads. +func (w *PollingClient) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) { + select { + case <-w.ctx.Done(): + return nil, ErrSubscriberClosed + default: + } + + headerCh, ok := channel.(chan<- *types.Header) + if !ok { + return nil, errors.New("invalid channel type") + } + if len(args) != 1 { + return nil, errors.New("invalid subscription args") + } + if args[0] != "newHeads" { + return nil, errors.New("unsupported subscription type") + } + + sub := make(chan *types.Header, 1) + w.mtx.Lock() + subID := w.subID + w.subID++ + w.subs[subID] = sub + w.mtx.Unlock() + + return event.NewSubscription(func(quit <-chan struct{}) error { + for { + select { + case header := <-sub: + headerCh <- header + case <-quit: + w.mtx.Lock() + delete(w.subs, subID) + w.mtx.Unlock() + return nil + case <-w.ctx.Done(): + return nil + } + } + }), nil +} + +func (w *PollingClient) pollHeads() { + // To prevent polls from stacking up in case HTTP requests + // are slow, use a similar model to the driver in which + // polls are requested manually after each header is fetched. + reqPollAfter := func() { + if w.pollRate == 0 { + return + } + time.AfterFunc(w.pollRate, w.reqPoll) + } + + reqPollAfter() + + defer close(w.closedCh) + + for { + select { + case <-w.pollReqCh: + // We don't need backoff here because we'll just try again + // after the pollRate elapses. + head, err := w.getLatestHeader() + if err != nil { + w.lgr.Error("error getting latest header", "err", err) + reqPollAfter() + continue + } + if w.currHead != nil && w.currHead.Hash() == head.Hash() { + w.lgr.Trace("no change in head, skipping notifications") + reqPollAfter() + continue + } + + w.lgr.Trace("notifying subscribers of new head", "head", head.Hash()) + w.currHead = head + w.mtx.RLock() + for _, sub := range w.subs { + sub <- head + } + w.mtx.RUnlock() + reqPollAfter() + case <-w.ctx.Done(): + w.c.Close() + return + } + } +} + +func (w *PollingClient) getLatestHeader() (*types.Header, error) { + ctx, cancel := context.WithTimeout(w.ctx, 5*time.Second) + defer cancel() + var head *types.Header + err := w.CallContext(ctx, &head, "eth_getBlockByNumber", "latest", false) + if err == nil && head == nil { + err = ethereum.NotFound + } + return head, err +} + +func (w *PollingClient) reqPoll() { + w.pollReqCh <- struct{}{} +} diff --git a/op-node/client/polling_test.go b/op-node/client/polling_test.go new file mode 100644 index 0000000000000..63c5b8df619dc --- /dev/null +++ b/op-node/client/polling_test.go @@ -0,0 +1,208 @@ +package client + +import ( + "context" + "errors" + "sync" + "testing" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" +) + +type MockRPC struct { + t *testing.T + callResults []*callResult + mtx sync.RWMutex + callCount int + autopop bool + closed bool +} + +type callResult struct { + root common.Hash + error error +} + +func (m *MockRPC) Close() { + m.closed = true +} + +func (m *MockRPC) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + m.mtx.Lock() + defer m.mtx.Unlock() + + if method != "eth_getBlockByNumber" { + m.t.Fatalf("invalid method %s", method) + } + if args[0] != "latest" { + m.t.Fatalf("invalid arg %v", args[0]) + } + + m.callCount++ + res := m.callResults[0] + headerP := result.(**types.Header) + *headerP = &types.Header{ + Root: res.root, + } + if m.autopop { + m.callResults = m.callResults[1:] + } + return res.error +} + +func (m *MockRPC) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + m.t.Fatal("BatchCallContext should not be called") + return nil +} + +func (m *MockRPC) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) { + m.t.Fatal("EthSubscribe should not be called") + return nil, nil +} + +func (m *MockRPC) popResult() { + m.mtx.Lock() + defer m.mtx.Unlock() + m.callResults = m.callResults[1:] +} + +func TestPollingClientSubscribeUnsubscribe(t *testing.T) { + lgr := log.New() + lgr.SetHandler(log.DiscardHandler()) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + root1 := common.Hash{0x01} + root2 := common.Hash{0x02} + root3 := common.Hash{0x03} + mockRPC := &MockRPC{ + t: t, + callResults: []*callResult{ + {root1, nil}, + {root2, nil}, + {root3, nil}, + }, + } + client := NewPollingClient(ctx, lgr, mockRPC, WithPollRate(0)) + + subs := make([]ethereum.Subscription, 0) + chans := make([]chan *types.Header, 0) + for i := 0; i < 2; i++ { + ch := make(chan *types.Header, 2) + sub, err := doSubscribe(client, ch) + require.NoError(t, err) + subs = append(subs, sub) + chans = append(chans, ch) + } + + client.reqPoll() + requireChansEqual(t, chans, root1) + mockRPC.popResult() + client.reqPoll() + requireChansEqual(t, chans, root2) + // Poll an additional time to show that responses with the same + // data don't notify again. + client.reqPoll() + + // Verify that no further notifications have been sent. + for _, ch := range chans { + select { + case <-ch: + t.Fatal("unexpected notification") + case <-time.NewTimer(10 * time.Millisecond).C: + continue + } + } + + mockRPC.popResult() + subs[0].Unsubscribe() + client.reqPoll() + select { + case <-chans[0]: + t.Fatal("unexpected notification") + case <-time.NewTimer(10 * time.Millisecond).C: + } + + header := <-chans[1] + require.Equal(t, root3, header.Root) +} + +func TestPollingClientErrorRecovery(t *testing.T) { + lgr := log.New() + lgr.SetHandler(log.DiscardHandler()) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + root := common.Hash{0x01} + mockRPC := &MockRPC{ + t: t, + callResults: []*callResult{ + {common.Hash{}, errors.New("foobar")}, + {common.Hash{}, errors.New("foobar")}, + {root, nil}, + }, + autopop: true, + } + client := NewPollingClient(ctx, lgr, mockRPC, WithPollRate(0)) + ch := make(chan *types.Header, 1) + sub, err := doSubscribe(client, ch) + require.NoError(t, err) + defer sub.Unsubscribe() + + for i := 0; i < 3; i++ { + client.reqPoll() + } + + header := <-ch + require.Equal(t, root, header.Root) + require.Equal(t, 3, mockRPC.callCount) +} + +func TestPollingClientClose(t *testing.T) { + lgr := log.New() + lgr.SetHandler(log.DiscardHandler()) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + root := common.Hash{0x01} + mockRPC := &MockRPC{ + t: t, + callResults: []*callResult{ + {root, nil}, + }, + autopop: true, + } + client := NewPollingClient(ctx, lgr, mockRPC, WithPollRate(0)) + ch := make(chan *types.Header, 1) + sub, err := doSubscribe(client, ch) + require.NoError(t, err) + client.reqPoll() + header := <-ch + cancel() + require.Nil(t, <-sub.Err()) + require.Equal(t, root, header.Root) + require.Equal(t, 1, mockRPC.callCount) + + // unsubscribe should be safe + sub.Unsubscribe() + + _, err = doSubscribe(client, ch) + require.Equal(t, ErrSubscriberClosed, err) +} + +func requireChansEqual(t *testing.T, chans []chan *types.Header, root common.Hash) { + for _, ch := range chans { + header := <-ch + require.Equal(t, root, header.Root) + } +} + +func doSubscribe(client RPC, ch chan<- *types.Header) (ethereum.Subscription, error) { + return client.EthSubscribe(context.Background(), ch, "newHeads") +} diff --git a/op-node/client/rpc.go b/op-node/client/rpc.go index 755ef34446c73..a321a3fb6680e 100644 --- a/op-node/client/rpc.go +++ b/op-node/client/rpc.go @@ -2,31 +2,99 @@ package client import ( "context" + "fmt" + "regexp" + "github.com/ethereum-optimism/optimism/op-service/backoff" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/log" "github.com/prometheus/client_golang/prometheus" "github.com/ethereum-optimism/optimism/op-node/metrics" "github.com/ethereum/go-ethereum/rpc" ) +var httpRegex = regexp.MustCompile("^http(s)?://") + type RPC interface { Close() CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error BatchCallContext(ctx context.Context, b []rpc.BatchElem) error - EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) + EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) +} + +// NewRPC returns the correct client.RPC instance for a given RPC url. +func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...rpc.ClientOption) (RPC, error) { + underlying, err := DialRPCClientWithBackoff(ctx, lgr, addr, opts...) + if err != nil { + return nil, err + } + + wrapped := &BaseRPCClient{ + c: underlying, + } + if httpRegex.MatchString(addr) { + return NewPollingClient(ctx, lgr, wrapped), nil + } + return wrapped, nil +} + +// Dials a JSON-RPC endpoint repeatedly, with a backoff, until a client connection is established. Auth is optional. +func DialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string, opts ...rpc.ClientOption) (*rpc.Client, error) { + bOff := backoff.Exponential() + var ret *rpc.Client + err := backoff.Do(10, bOff, func() error { + client, err := rpc.DialOptions(ctx, addr, opts...) + if err != nil { + if client == nil { + return fmt.Errorf("failed to dial address (%s): %w", addr, err) + } + log.Warn("failed to dial address, but may connect later", "addr", addr, "err", err) + } + ret = client + return nil + }) + if err != nil { + return nil, err + } + return ret, nil +} + +// BaseRPCClient is a wrapper around a concrete *rpc.Client instance to make it compliant +// with the client.RPC interface. +type BaseRPCClient struct { + c *rpc.Client +} + +func NewBaseRPCClient(c *rpc.Client) *BaseRPCClient { + return &BaseRPCClient{c: c} +} + +func (b *BaseRPCClient) Close() { + b.c.Close() +} + +func (b *BaseRPCClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + return b.c.CallContext(ctx, result, method, args...) +} + +func (b *BaseRPCClient) BatchCallContext(ctx context.Context, batch []rpc.BatchElem) error { + return b.c.BatchCallContext(ctx, batch) +} + +func (b *BaseRPCClient) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) { + return b.c.EthSubscribe(ctx, channel, args...) } // InstrumentedRPCClient is an RPC client that tracks // Prometheus metrics for each call. type InstrumentedRPCClient struct { - c *rpc.Client + c RPC m *metrics.Metrics } -// NewInstrumentedRPC creates a new instrumented RPC client. It takes -// a concrete *rpc.Client to prevent people from passing in an already -// instrumented client. -func NewInstrumentedRPC(c *rpc.Client, m *metrics.Metrics) *InstrumentedRPCClient { +// NewInstrumentedRPC creates a new instrumented RPC client. +func NewInstrumentedRPC(c RPC, m *metrics.Metrics) *InstrumentedRPCClient { return &InstrumentedRPCClient{ c: c, m: m, @@ -49,14 +117,10 @@ func (ic *InstrumentedRPCClient) BatchCallContext(ctx context.Context, b []rpc.B }, b) } -func (ic *InstrumentedRPCClient) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) { +func (ic *InstrumentedRPCClient) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) { return ic.c.EthSubscribe(ctx, channel, args...) } -func (ic *InstrumentedRPCClient) Client() Client { - return NewInstrumentedClient(ic.c, ic.m) -} - // instrumentBatch handles metrics for batch calls. Request metrics are // increased for each batch element. Request durations are tracked for // the batch as a whole using a special method. Errors are tracked diff --git a/op-node/go.mod b/op-node/go.mod index 16c84d0384525..ea33061f17e88 100644 --- a/op-node/go.mod +++ b/op-node/go.mod @@ -5,8 +5,9 @@ go 1.18 require ( github.com/btcsuite/btcd/btcec/v2 v2.2.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 - github.com/ethereum-optimism/optimism/op-bindings v0.8.8 - github.com/ethereum-optimism/optimism/op-chain-ops v0.8.8 + github.com/ethereum-optimism/optimism/op-bindings v0.8.10 + github.com/ethereum-optimism/optimism/op-chain-ops v0.8.10 + github.com/ethereum-optimism/optimism/op-service v0.8.10 github.com/ethereum/go-ethereum v1.10.23 github.com/golang/snappy v0.0.4 github.com/google/go-cmp v0.5.8 diff --git a/op-node/go.sum b/op-node/go.sum index 3508e2f95d8b1..af91e37eb7d2a 100644 --- a/op-node/go.sum +++ b/op-node/go.sum @@ -190,10 +190,12 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd h1:NchOnosWOkH9wlix8QevGHE+6vuRa+OMGvDNsczv2kQ= github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8 h1:HN625JI2VsRsli+U6GAXipg7lAKx8EOmGIovN79Az+I= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= -github.com/ethereum-optimism/optimism/op-chain-ops v0.8.8 h1:wNn80nhMW4srM/TvA785mikElpPJhEtTLBBuYFxjUCM= -github.com/ethereum-optimism/optimism/op-chain-ops v0.8.8/go.mod h1:l9YB+bMCfYZV6rjcC6XL0VHa+6hkgdVPioHwBL9u6r8= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10 h1:aSAWCQwBQnbmv03Gvtuvn3qfTWrZu/sTlRAWrpQhiHc= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= +github.com/ethereum-optimism/optimism/op-chain-ops v0.8.10 h1:ErDuEO7Dsd7+XXlTWToBN/388IgC8eXjAPgiHoXviw4= +github.com/ethereum-optimism/optimism/op-chain-ops v0.8.10/go.mod h1:a9/PrzVU8EHKlLr6yz4YXw2VhEHYrbVogX56r26VUrY= +github.com/ethereum-optimism/optimism/op-service v0.8.10 h1:K3IABHI1b0MDrDXALvTKTbzy6IogGD6NgmbqfKEcEwM= +github.com/ethereum-optimism/optimism/op-service v0.8.10/go.mod h1:K0uybOhICTc2yfhrRj0cD1m7aPkOf5C9e6bUmvf4rGA= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 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= diff --git a/op-node/node/api.go b/op-node/node/api.go index 3d2637688e95d..e5a4b14c5ec45 100644 --- a/op-node/node/api.go +++ b/op-node/node/api.go @@ -6,7 +6,6 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-node/eth" - "github.com/ethereum-optimism/optimism/op-node/metrics" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/version" "github.com/ethereum/go-ethereum" @@ -26,12 +25,17 @@ type driverClient interface { ResetDerivationPipeline(context.Context) error } +type rpcMetrics interface { + // RecordRPCServerRequest returns a function that records the duration of serving the given RPC method + RecordRPCServerRequest(method string) func() +} + type adminAPI struct { dr driverClient - m *metrics.Metrics + m rpcMetrics } -func newAdminAPI(dr driverClient, m *metrics.Metrics) *adminAPI { +func NewAdminAPI(dr driverClient, m rpcMetrics) *adminAPI { return &adminAPI{ dr: dr, m: m, @@ -49,10 +53,10 @@ type nodeAPI struct { client l2EthClient dr driverClient log log.Logger - m *metrics.Metrics + m rpcMetrics } -func newNodeAPI(config *rollup.Config, l2Client l2EthClient, dr driverClient, log log.Logger, m *metrics.Metrics) *nodeAPI { +func NewNodeAPI(config *rollup.Config, l2Client l2EthClient, dr driverClient, log log.Logger, m rpcMetrics) *nodeAPI { return &nodeAPI{ config: config, client: l2Client, diff --git a/op-node/node/client.go b/op-node/node/client.go index ebf4f6c404ca4..6e7f1e36043b3 100644 --- a/op-node/node/client.go +++ b/op-node/node/client.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/ethereum-optimism/optimism/op-node/backoff" + "github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum/go-ethereum/log" gn "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" @@ -13,13 +13,13 @@ import ( type L2EndpointSetup interface { // Setup a RPC client to a L2 execution engine to process rollup blocks with. - Setup(ctx context.Context, log log.Logger) (cl *rpc.Client, err error) + Setup(ctx context.Context, log log.Logger) (cl client.RPC, err error) Check() error } type L1EndpointSetup interface { // Setup a RPC client to a L1 node to pull rollup input-data from. - Setup(ctx context.Context, log log.Logger) (cl *rpc.Client, trust bool, err error) + Setup(ctx context.Context, log log.Logger) (cl client.RPC, trust bool, err error) } type L2EndpointConfig struct { @@ -40,12 +40,12 @@ func (cfg *L2EndpointConfig) Check() error { return nil } -func (cfg *L2EndpointConfig) Setup(ctx context.Context, log log.Logger) (*rpc.Client, error) { +func (cfg *L2EndpointConfig) Setup(ctx context.Context, log log.Logger) (client.RPC, error) { if err := cfg.Check(); err != nil { return nil, err } auth := rpc.WithHTTPAuth(gn.NewJWTAuth(cfg.L2EngineJWTSecret)) - l2Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L2EngineAddr, auth) + l2Node, err := client.NewRPC(ctx, log, cfg.L2EngineAddr, auth) if err != nil { return nil, err } @@ -55,7 +55,7 @@ func (cfg *L2EndpointConfig) Setup(ctx context.Context, log log.Logger) (*rpc.Cl // PreparedL2Endpoints enables testing with in-process pre-setup RPC connections to L2 engines type PreparedL2Endpoints struct { - Client *rpc.Client + Client client.RPC } func (p *PreparedL2Endpoints) Check() error { @@ -67,7 +67,7 @@ func (p *PreparedL2Endpoints) Check() error { var _ L2EndpointSetup = (*PreparedL2Endpoints)(nil) -func (p *PreparedL2Endpoints) Setup(ctx context.Context, log log.Logger) (*rpc.Client, error) { +func (p *PreparedL2Endpoints) Setup(ctx context.Context, log log.Logger) (client.RPC, error) { return p.Client, nil } @@ -82,8 +82,8 @@ type L1EndpointConfig struct { var _ L1EndpointSetup = (*L1EndpointConfig)(nil) -func (cfg *L1EndpointConfig) Setup(ctx context.Context, log log.Logger) (cl *rpc.Client, trust bool, err error) { - l1Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L1NodeAddr) +func (cfg *L1EndpointConfig) Setup(ctx context.Context, log log.Logger) (cl client.RPC, trust bool, err error) { + l1Node, err := client.NewRPC(ctx, log, cfg.L1NodeAddr) if err != nil { return nil, false, fmt.Errorf("failed to dial L1 address (%s): %w", cfg.L1NodeAddr, err) } @@ -92,33 +92,12 @@ func (cfg *L1EndpointConfig) Setup(ctx context.Context, log log.Logger) (cl *rpc // PreparedL1Endpoint enables testing with an in-process pre-setup RPC connection to L1 type PreparedL1Endpoint struct { - Client *rpc.Client + Client client.RPC TrustRPC bool } var _ L1EndpointSetup = (*PreparedL1Endpoint)(nil) -func (p *PreparedL1Endpoint) Setup(ctx context.Context, log log.Logger) (cl *rpc.Client, trust bool, err error) { +func (p *PreparedL1Endpoint) Setup(ctx context.Context, log log.Logger) (cl client.RPC, trust bool, err error) { return p.Client, p.TrustRPC, nil } - -// Dials a JSON-RPC endpoint repeatedly, with a backoff, until a client connection is established. Auth is optional. -func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string, opts ...rpc.ClientOption) (*rpc.Client, error) { - bOff := backoff.Exponential() - var ret *rpc.Client - err := backoff.Do(10, bOff, func() error { - client, err := rpc.DialOptions(ctx, addr, opts...) - if err != nil { - if client == nil { - return fmt.Errorf("failed to dial address (%s): %w", addr, err) - } - log.Warn("failed to dial address, but may connect later", "addr", addr, "err", err) - } - ret = client - return nil - }) - if err != nil { - return nil, err - } - return ret, nil -} diff --git a/op-node/node/log.go b/op-node/node/log.go index 855fd4f06abe6..bf2edbc23b0b9 100644 --- a/op-node/node/log.go +++ b/op-node/node/log.go @@ -44,7 +44,7 @@ func (cfg *LogConfig) Check() error { func (cfg *LogConfig) NewLogger() log.Logger { handler := log.StreamHandler(os.Stdout, format(cfg.Format, cfg.Color)) handler = log.SyncHandler(handler) - log.LvlFilterHandler(level(cfg.Level), handler) + handler = log.LvlFilterHandler(level(cfg.Level), handler) logger := log.New() logger.SetHandler(handler) return logger diff --git a/op-node/node/node.go b/op-node/node/node.go index e1fbf98187a6a..b85de8f24729e 100644 --- a/op-node/node/node.go +++ b/op-node/node/node.go @@ -8,15 +8,16 @@ import ( "github.com/hashicorp/go-multierror" "github.com/libp2p/go-libp2p-core/peer" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/metrics" "github.com/ethereum-optimism/optimism/op-node/p2p" "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/sources" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" ) type OpNode struct { @@ -170,7 +171,7 @@ func (n *OpNode) initRPCServer(ctx context.Context, cfg *Config) error { n.server.EnableP2P(p2p.NewP2PAPIBackend(n.p2pNode, n.log, n.metrics)) } if cfg.RPC.EnableAdmin { - n.server.EnableAdminAPI(newAdminAPI(n.l2Driver, n.metrics)) + n.server.EnableAdminAPI(NewAdminAPI(n.l2Driver, n.metrics)) } n.log.Info("Starting JSON-RPC server") if err := n.server.Start(); err != nil { @@ -220,11 +221,8 @@ func (n *OpNode) initP2PSigner(ctx context.Context, cfg *Config) error { func (n *OpNode) Start(ctx context.Context) error { n.log.Info("Starting execution engine driver") - // Request initial head update, default to genesis otherwise - reqCtx, reqCancel := context.WithTimeout(ctx, time.Second*10) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine - err := n.l2Driver.Start(reqCtx) - reqCancel() + err := n.l2Driver.Start() if err != nil { n.log.Error("Could not start a rollup node", "err", err) return err @@ -355,3 +353,11 @@ func (n *OpNode) Close() error { } return result.ErrorOrNil() } + +func (n *OpNode) ListenAddr() string { + return n.server.listenAddr.String() +} + +func (n *OpNode) HTTPEndpoint() string { + return fmt.Sprintf("http://%s", n.ListenAddr()) +} diff --git a/op-node/node/server.go b/op-node/node/server.go index c485747b795bc..e083fec770327 100644 --- a/op-node/node/server.go +++ b/op-node/node/server.go @@ -29,7 +29,7 @@ type rpcServer struct { } func newRPCServer(ctx context.Context, rpcCfg *RPCConfig, rollupCfg *rollup.Config, l2Client l2EthClient, dr driverClient, log log.Logger, appVersion string, m *metrics.Metrics) (*rpcServer, error) { - api := newNodeAPI(rollupCfg, l2Client, dr, log.New("rpc", "node"), m) + api := NewNodeAPI(rollupCfg, l2Client, dr, log.New("rpc", "node"), m) // TODO: extend RPC config with options for WS, IPC and HTTP RPC connections endpoint := net.JoinHostPort(rpcCfg.ListenAddr, strconv.Itoa(rpcCfg.ListenPort)) r := &rpcServer{ diff --git a/op-node/node/server_test.go b/op-node/node/server_test.go index bac92cf3c1b8a..83b9206551875 100644 --- a/op-node/node/server_test.go +++ b/op-node/node/server_test.go @@ -6,6 +6,7 @@ import ( "math/rand" "testing" + rpcclient "github.com/ethereum-optimism/optimism/op-node/client" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -101,7 +102,7 @@ func TestOutputAtBlock(t *testing.T) { assert.NoError(t, server.Start()) defer server.Stop() - client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String()) + client, err := rpcclient.DialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String()) assert.NoError(t, err) var out []eth.Bytes32 @@ -127,7 +128,7 @@ func TestVersion(t *testing.T) { assert.NoError(t, server.Start()) defer server.Stop() - client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String()) + client, err := rpcclient.DialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String()) assert.NoError(t, err) var out string @@ -162,7 +163,7 @@ func TestSyncStatus(t *testing.T) { assert.NoError(t, server.Start()) defer server.Stop() - client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String()) + client, err := rpcclient.DialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String()) assert.NoError(t, err) var out *eth.SyncStatus diff --git a/op-node/p2p/gossip.go b/op-node/p2p/gossip.go index 68746d2632a11..373c90da2514c 100644 --- a/op-node/p2p/gossip.go +++ b/op-node/p2p/gossip.go @@ -224,7 +224,11 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx signatureBytes, payloadBytes := data[:65], data[65:] // [REJECT] if the signature by the sequencer is not valid - signingHash := BlockSigningHash(cfg, payloadBytes) + signingHash, err := BlockSigningHash(cfg, payloadBytes) + if err != nil { + log.Warn("failed to compute block signing hash", "err", err, "peer", id) + return pubsub.ValidationReject + } pub, err := crypto.SigToPub(signingHash[:], signatureBytes) if err != nil { diff --git a/op-node/p2p/signer.go b/op-node/p2p/signer.go index b7914b6ae8f84..c52e5c2927f73 100644 --- a/op-node/p2p/signer.go +++ b/op-node/p2p/signer.go @@ -23,19 +23,22 @@ type Signer interface { io.Closer } -func SigningHash(domain [32]byte, chainID *big.Int, payloadBytes []byte) common.Hash { +func SigningHash(domain [32]byte, chainID *big.Int, payloadBytes []byte) (common.Hash, error) { var msgInput [32 + 32 + 32]byte // domain: first 32 bytes copy(msgInput[:32], domain[:]) // chain_id: second 32 bytes + if chainID.BitLen() > 256 { + return common.Hash{}, errors.New("chain_id is too large") + } chainID.FillBytes(msgInput[32:64]) // payload_hash: third 32 bytes, hash of encoded payload copy(msgInput[32:], crypto.Keccak256(payloadBytes)) - return crypto.Keccak256Hash(msgInput[:]) + return crypto.Keccak256Hash(msgInput[:]), nil } -func BlockSigningHash(cfg *rollup.Config, payloadBytes []byte) common.Hash { +func BlockSigningHash(cfg *rollup.Config, payloadBytes []byte) (common.Hash, error) { return SigningHash(SigningDomainBlocksV1, cfg.L2ChainID, payloadBytes) } @@ -52,7 +55,10 @@ func (s *LocalSigner) Sign(ctx context.Context, domain [32]byte, chainID *big.In if s.priv == nil { return nil, errors.New("signer is closed") } - signingHash := SigningHash(domain, chainID, encodedMsg) + signingHash, err := SigningHash(domain, chainID, encodedMsg) + if err != nil { + return nil, err + } signature, err := crypto.Sign(signingHash[:], s.priv) if err != nil { return nil, err diff --git a/op-node/rollup/derive/attributes.go b/op-node/rollup/derive/attributes.go index 0a5b8504544a3..8551fa02ed6f2 100644 --- a/op-node/rollup/derive/attributes.go +++ b/op-node/rollup/derive/attributes.go @@ -3,7 +3,6 @@ package derive import ( "context" "fmt" - "io" "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/rollup" @@ -15,7 +14,7 @@ import ( // L1ReceiptsFetcher fetches L1 header info and receipts for the payload attributes derivation (the info tx and deposits) type L1ReceiptsFetcher interface { InfoByHash(ctx context.Context, hash common.Hash) (eth.BlockInfo, error) - Fetch(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, eth.ReceiptsFetcher, error) + FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) } // PreparePayloadAttributes prepares a PayloadAttributes template that is ready to build a L2 block with deposits only, on top of the given l2Parent, with the given epoch as L1 origin. @@ -32,7 +31,7 @@ func PreparePayloadAttributes(ctx context.Context, cfg *rollup.Config, dl L1Rece // case we need to fetch all transaction receipts from the L1 origin block so we can scan for // user deposits. if l2Parent.L1Origin.Number != epoch.Number { - info, _, receiptsFetcher, err := dl.Fetch(ctx, epoch.Hash) + info, receipts, err := dl.FetchReceipts(ctx, epoch.Hash) if err != nil { return nil, NewTemporaryError(fmt.Errorf("failed to fetch L1 block info and receipts: %w", err)) } @@ -41,17 +40,7 @@ func PreparePayloadAttributes(ctx context.Context, cfg *rollup.Config, dl L1Rece fmt.Errorf("cannot create new block with L1 origin %s (parent %s) on top of L1 origin %s", epoch, info.ParentHash(), l2Parent.L1Origin)) } - for { - if err := receiptsFetcher.Fetch(ctx); err == io.EOF { - break - } else if err != nil { - return nil, NewTemporaryError(fmt.Errorf("failed to fetch more receipts: %w", err)) - } - } - receipts, err := receiptsFetcher.Result() - if err != nil { - return nil, NewResetError(fmt.Errorf("fetched bad receipt data: %w", err)) - } + deposits, err := DeriveDeposits(receipts, cfg.DepositContractAddress) if err != nil { // deposits may never be ignored. Failing to process them is a critical error. diff --git a/op-node/rollup/derive/attributes_test.go b/op-node/rollup/derive/attributes_test.go index 58d5662331807..84f4581ae07cd 100644 --- a/op-node/rollup/derive/attributes_test.go +++ b/op-node/rollup/derive/attributes_test.go @@ -36,7 +36,7 @@ func TestPreparePayloadAttributes(t *testing.T) { l1Info := testutils.RandomBlockInfo(rng) l1Info.InfoNum = l2Parent.L1Origin.Number + 1 epoch := l1Info.ID() - l1Fetcher.ExpectFetch(epoch.Hash, l1Info, nil, nil, nil) + l1Fetcher.ExpectFetchReceipts(epoch.Hash, l1Info, nil, nil) _, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, l2Time, epoch) require.NotNil(t, err, "inconsistent L1 origin error expected") require.ErrorIs(t, err, ErrReset, "inconsistent L1 origin transition must be handled like a critical error with reorg") @@ -63,7 +63,7 @@ func TestPreparePayloadAttributes(t *testing.T) { epoch := l2Parent.L1Origin epoch.Number += 1 mockRPCErr := errors.New("mock rpc error") - l1Fetcher.ExpectFetch(epoch.Hash, nil, nil, nil, mockRPCErr) + l1Fetcher.ExpectFetchReceipts(epoch.Hash, nil, nil, mockRPCErr) _, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, l2Time, epoch) require.ErrorIs(t, err, mockRPCErr, "mock rpc error expected") require.ErrorIs(t, err, ErrTemporary, "rpc errors should not be critical, it is not necessary to reorg") @@ -93,7 +93,7 @@ func TestPreparePayloadAttributes(t *testing.T) { epoch := l1Info.ID() l1InfoTx, err := L1InfoDepositBytes(0, l1Info) require.NoError(t, err) - l1Fetcher.ExpectFetch(epoch.Hash, l1Info, nil, nil, nil) + l1Fetcher.ExpectFetchReceipts(epoch.Hash, l1Info, nil, nil) attrs, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, l2Time, epoch) require.NoError(t, err) require.NotNil(t, attrs) @@ -114,12 +114,13 @@ func TestPreparePayloadAttributes(t *testing.T) { l1Info.InfoParentHash = l2Parent.L1Origin.Hash l1Info.InfoNum = l2Parent.L1Origin.Number + 1 - receipts, depositTxs := makeReceipts(rng, l1Info.InfoHash, cfg.DepositContractAddress, []receiptData{ + receipts, depositTxs, err := makeReceipts(rng, l1Info.InfoHash, cfg.DepositContractAddress, []receiptData{ {goodReceipt: true, DepositLogs: []bool{true, false}}, {goodReceipt: true, DepositLogs: []bool{true}}, {goodReceipt: false, DepositLogs: []bool{true}}, {goodReceipt: false, DepositLogs: []bool{false}}, }) + require.NoError(t, err) usedDepositTxs, err := encodeDeposits(depositTxs) require.NoError(t, err) @@ -129,9 +130,7 @@ func TestPreparePayloadAttributes(t *testing.T) { l2Txs := append(append(make([]eth.Data, 0), l1InfoTx), usedDepositTxs...) - // txs are ignored, API is a bit bloated to previous approach. Only l1Info and receipts matter. - l1Txs := make(types.Transactions, len(receipts)) - l1Fetcher.ExpectFetch(epoch.Hash, l1Info, l1Txs, receipts, nil) + l1Fetcher.ExpectFetchReceipts(epoch.Hash, l1Info, receipts, nil) attrs, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, l2Time, epoch) require.NoError(t, err) require.NotNil(t, attrs) diff --git a/op-node/rollup/derive/batch_queue.go b/op-node/rollup/derive/batch_queue.go index 5e5dd5496ff62..18a987661af22 100644 --- a/op-node/rollup/derive/batch_queue.go +++ b/op-node/rollup/derive/batch_queue.go @@ -26,12 +26,6 @@ import ( // It is internally responsible for making sure that batches with L1 inclusions block outside it's // working range are not considered or pruned. -type BatchQueueOutput interface { - StageProgress - AddBatch(batch *BatchData) - SafeL2Head() eth.L2BlockRef -} - type NextBatchProvider interface { Origin() eth.L1BlockRef NextBatch(ctx context.Context) (*BatchData, error) @@ -154,7 +148,7 @@ func (bq *BatchQueue) deriveNextBatch(ctx context.Context, outOfData bool, l2Saf epoch := bq.l1Blocks[0] if l2SafeHead.L1Origin != epoch.ID() { - return nil, NewResetError(fmt.Errorf("buffered L1 chain epoch %s in batch queue does not match safe head %s", epoch, l2SafeHead)) + return nil, NewResetError(fmt.Errorf("buffered L1 chain epoch %s in batch queue does not match safe head origin %s", epoch, l2SafeHead.L1Origin)) } // Find the first-seen batch that matches all validity conditions. diff --git a/op-node/rollup/derive/channel_bank.go b/op-node/rollup/derive/channel_bank.go index 9a4581051cddc..dfcd048d65b63 100644 --- a/op-node/rollup/derive/channel_bank.go +++ b/op-node/rollup/derive/channel_bank.go @@ -38,7 +38,7 @@ type ChannelBank struct { fetcher L1Fetcher } -var _ PullStage = (*ChannelBank)(nil) +var _ ResetableStage = (*ChannelBank)(nil) // NewChannelBank creates a ChannelBank, which should be Reset(origin) before use. func NewChannelBank(log log.Logger, cfg *rollup.Config, prev NextDataProvider, fetcher L1Fetcher) *ChannelBank { diff --git a/op-node/rollup/derive/channel_in_reader.go b/op-node/rollup/derive/channel_in_reader.go index 9865dacd5aa7f..07156b9997a97 100644 --- a/op-node/rollup/derive/channel_in_reader.go +++ b/op-node/rollup/derive/channel_in_reader.go @@ -22,7 +22,7 @@ type ChannelInReader struct { prev *ChannelBank } -var _ PullStage = (*ChannelInReader)(nil) +var _ ResetableStage = (*ChannelInReader)(nil) // NewChannelInReader creates a ChannelInReader, which should be Reset(origin) before use. func NewChannelInReader(log log.Logger, prev *ChannelBank) *ChannelInReader { diff --git a/op-node/rollup/derive/deposit_log.go b/op-node/rollup/derive/deposit_log.go index 1a217a8c84feb..3215d0452fbb4 100644 --- a/op-node/rollup/derive/deposit_log.go +++ b/op-node/rollup/derive/deposit_log.go @@ -140,7 +140,7 @@ func unmarshalDepositVersion0(dep *types.DepositTx, to common.Address, opaqueDat // MarshalDepositLogEvent returns an EVM log entry that encodes a TransactionDeposited event from the deposit contract. // This is the reverse of the deposit transaction derivation. -func MarshalDepositLogEvent(depositContractAddr common.Address, deposit *types.DepositTx) *types.Log { +func MarshalDepositLogEvent(depositContractAddr common.Address, deposit *types.DepositTx) (*types.Log, error) { toBytes := common.Hash{} if deposit.To != nil { toBytes = deposit.To.Hash() @@ -157,7 +157,10 @@ func MarshalDepositLogEvent(depositContractAddr common.Address, deposit *types.D // opaqueData slice content offset: value will always be 0x20. binary.BigEndian.PutUint64(data[32-8:32], 32) - opaqueData := marshalDepositVersion0(deposit) + opaqueData, err := marshalDepositVersion0(deposit) + if err != nil { + return &types.Log{}, err + } // opaqueData slice length binary.BigEndian.PutUint64(data[64-8:64], uint64(len(opaqueData))) @@ -182,20 +185,26 @@ func MarshalDepositLogEvent(depositContractAddr common.Address, deposit *types.D TxIndex: 0, BlockHash: common.Hash{}, Index: 0, - } + }, nil } -func marshalDepositVersion0(deposit *types.DepositTx) (opaqueData []byte) { - opaqueData = make([]byte, 32+32+8+1, 32+32+8+1+len(deposit.Data)) +func marshalDepositVersion0(deposit *types.DepositTx) ([]byte, error) { + opaqueData := make([]byte, 32+32+8+1, 32+32+8+1+len(deposit.Data)) offset := 0 // uint256 mint if deposit.Mint != nil { + if deposit.Mint.BitLen() > 256 { + return nil, fmt.Errorf("mint value exceeds 256 bits: %d", deposit.Mint) + } deposit.Mint.FillBytes(opaqueData[offset : offset+32]) } offset += 32 // uint256 value + if deposit.Value.BitLen() > 256 { + return nil, fmt.Errorf("value value exceeds 256 bits: %d", deposit.Value) + } deposit.Value.FillBytes(opaqueData[offset : offset+32]) offset += 32 @@ -211,5 +220,5 @@ func marshalDepositVersion0(deposit *types.DepositTx) (opaqueData []byte) { // Deposit data then fills the remaining event data opaqueData = append(opaqueData, deposit.Data...) - return opaqueData + return opaqueData, nil } diff --git a/op-node/rollup/derive/deposit_log_test.go b/op-node/rollup/derive/deposit_log_test.go index 948b041521229..b5c2465d4494a 100644 --- a/op-node/rollup/derive/deposit_log_test.go +++ b/op-node/rollup/derive/deposit_log_test.go @@ -23,7 +23,10 @@ func TestUnmarshalLogEvent(t *testing.T) { LogIndex: uint64(rng.Intn(10000)), } depInput := testutils.GenerateDeposit(source.SourceHash(), rng) - log := MarshalDepositLogEvent(MockDepositContractAddr, depInput) + log, err := MarshalDepositLogEvent(MockDepositContractAddr, depInput) + if err != nil { + t.Fatal(err) + } log.TxIndex = uint(rng.Intn(10000)) log.Index = uint(source.LogIndex) @@ -47,8 +50,10 @@ type receiptData struct { DepositLogs []bool } -func makeReceipts(rng *rand.Rand, blockHash common.Hash, depositContractAddr common.Address, testReceipts []receiptData) (receipts []*types.Receipt, expectedDeposits []*types.DepositTx) { +func makeReceipts(rng *rand.Rand, blockHash common.Hash, depositContractAddr common.Address, testReceipts []receiptData) ([]*types.Receipt, []*types.DepositTx, error) { logIndex := uint(0) + receipts := []*types.Receipt{} + expectedDeposits := []*types.DepositTx{} for txIndex, rData := range testReceipts { var logs []*types.Log status := types.ReceiptStatusSuccessful @@ -57,13 +62,17 @@ func makeReceipts(rng *rand.Rand, blockHash common.Hash, depositContractAddr com } for _, isDeposit := range rData.DepositLogs { var ev *types.Log + var err error if isDeposit { source := UserDepositSource{L1BlockHash: blockHash, LogIndex: uint64(logIndex)} dep := testutils.GenerateDeposit(source.SourceHash(), rng) if status == types.ReceiptStatusSuccessful { expectedDeposits = append(expectedDeposits, dep) } - ev = MarshalDepositLogEvent(depositContractAddr, dep) + ev, err = MarshalDepositLogEvent(depositContractAddr, dep) + if err != nil { + return []*types.Receipt{}, []*types.DepositTx{}, err + } } else { ev = testutils.GenerateLog(testutils.RandomAddress(rng), nil, nil) } @@ -82,7 +91,7 @@ func makeReceipts(rng *rand.Rand, blockHash common.Hash, depositContractAddr com TransactionIndex: uint(txIndex), }) } - return + return receipts, expectedDeposits, nil } type DeriveUserDepositsTestCase struct { @@ -108,7 +117,10 @@ func TestDeriveUserDeposits(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { rng := rand.New(rand.NewSource(1234 + int64(i))) blockHash := testutils.RandomHash(rng) - receipts, expectedDeposits := makeReceipts(rng, blockHash, MockDepositContractAddr, testCase.receipts) + receipts, expectedDeposits, err := makeReceipts(rng, blockHash, MockDepositContractAddr, testCase.receipts) + if err != nil { + t.Fatal(err) + } got, err := UserDeposits(receipts, MockDepositContractAddr) require.NoError(t, err) require.Equal(t, len(got), len(expectedDeposits)) diff --git a/op-node/rollup/derive/engine_queue.go b/op-node/rollup/derive/engine_queue.go index b585619dde36b..ae4cac54aa530 100644 --- a/op-node/rollup/derive/engine_queue.go +++ b/op-node/rollup/derive/engine_queue.go @@ -78,13 +78,14 @@ type EngineQueue struct { engine Engine prev NextAttributesProvider - progress Progress // only used for pipeline resets + origin eth.L1BlockRef // only used for pipeline resets - metrics Metrics + metrics Metrics + l1Fetcher L1Fetcher } // NewEngineQueue creates a new EngineQueue, which should be Reset(origin) before use. -func NewEngineQueue(log log.Logger, cfg *rollup.Config, engine Engine, metrics Metrics, prev NextAttributesProvider) *EngineQueue { +func NewEngineQueue(log log.Logger, cfg *rollup.Config, engine Engine, metrics Metrics, prev NextAttributesProvider, l1Fetcher L1Fetcher) *EngineQueue { return &EngineQueue{ log: log, cfg: cfg, @@ -95,12 +96,13 @@ func NewEngineQueue(log log.Logger, cfg *rollup.Config, engine Engine, metrics M MaxSize: maxUnsafePayloadsMemory, SizeFn: payloadMemSize, }, - prev: prev, + prev: prev, + l1Fetcher: l1Fetcher, } } -func (eq *EngineQueue) Progress() Progress { - return eq.progress +func (eq *EngineQueue) Origin() eth.L1BlockRef { + return eq.origin } func (eq *EngineQueue) SetUnsafeHead(head eth.L2BlockRef) { @@ -151,7 +153,7 @@ func (eq *EngineQueue) LastL2Time() uint64 { return uint64(eq.safeAttributes[len(eq.safeAttributes)-1].Timestamp) } -func (eq *EngineQueue) Step(ctx context.Context, _ Progress) error { +func (eq *EngineQueue) Step(ctx context.Context) error { if len(eq.safeAttributes) > 0 { return eq.tryNextSafeAttributes(ctx) } @@ -402,13 +404,13 @@ func (eq *EngineQueue) forceNextSafeAttributes(ctx context.Context) error { // ResetStep Walks the L2 chain backwards until it finds an L2 block whose L1 origin is canonical. // The unsafe head is set to the head of the L2 chain, unless the existing safe head is not canonical. -func (eq *EngineQueue) ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error { - result, err := sync.FindL2Heads(ctx, eq.cfg, l1Fetcher, eq.engine) +func (eq *EngineQueue) Reset(ctx context.Context, _ eth.L1BlockRef) error { + result, err := sync.FindL2Heads(ctx, eq.cfg, eq.l1Fetcher, eq.engine) if err != nil { return NewTemporaryError(fmt.Errorf("failed to find the L2 Heads to start from: %w", err)) } finalized, safe, unsafe := result.Finalized, result.Safe, result.Unsafe - l1Origin, err := l1Fetcher.L1BlockRefByHash(ctx, safe.L1Origin.Hash) + l1Origin, err := eq.l1Fetcher.L1BlockRefByHash(ctx, safe.L1Origin.Hash) if err != nil { return NewTemporaryError(fmt.Errorf("failed to fetch the new L1 progress: origin: %v; err: %w", safe.L1Origin, err)) } @@ -421,7 +423,7 @@ func (eq *EngineQueue) ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error if l1Origin.Number < eq.cfg.ChannelTimeout { pipelineNumber = 0 } - pipelineOrigin, err := l1Fetcher.L1BlockRefByNumber(ctx, pipelineNumber) + pipelineOrigin, err := eq.l1Fetcher.L1BlockRefByNumber(ctx, pipelineNumber) if err != nil { return NewTemporaryError(fmt.Errorf("failed to fetch the new L1 progress: origin: %v; err: %w", pipelineNumber, err)) } @@ -431,9 +433,7 @@ func (eq *EngineQueue) ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error eq.finalized = finalized eq.finalityData = eq.finalityData[:0] // note: we do not clear the unsafe payloadds queue; if the payloads are not applicable anymore the parent hash checks will clear out the old payloads. - eq.progress = Progress{ - Origin: pipelineOrigin, - } + eq.origin = pipelineOrigin eq.metrics.RecordL2Ref("l2_finalized", finalized) eq.metrics.RecordL2Ref("l2_safe", safe) eq.metrics.RecordL2Ref("l2_unsafe", unsafe) diff --git a/op-node/rollup/derive/engine_queue_test.go b/op-node/rollup/derive/engine_queue_test.go index 800c5c7736fe8..bc09bad092b4d 100644 --- a/op-node/rollup/derive/engine_queue_test.go +++ b/op-node/rollup/derive/engine_queue_test.go @@ -8,12 +8,13 @@ import ( "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testutils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" ) type fakeAttributesQueue struct { @@ -193,7 +194,7 @@ func TestEngineQueue_Finalize(t *testing.T) { t.Log("refF0", refF0.Hash) t.Log("refF1", refF1.Hash) - metrics := &TestMetrics{} + metrics := &testutils.TestDerivationMetrics{} eng := &testutils.MockEngine{} // we find the common point to initialize to by comparing the L1 origins in the L2 chain with the L1 chain l1F := &testutils.MockL1Source{} @@ -229,21 +230,21 @@ func TestEngineQueue_Finalize(t *testing.T) { prev := &fakeAttributesQueue{} - eq := NewEngineQueue(logger, cfg, eng, metrics, prev) - require.ErrorIs(t, eq.ResetStep(context.Background(), l1F), io.EOF) + eq := NewEngineQueue(logger, cfg, eng, metrics, prev, l1F) + require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}), io.EOF) require.Equal(t, refB1, eq.SafeL2Head(), "L2 reset should go back to sequence window ago: blocks with origin E and D are not safe until we reconcile, C is extra, and B1 is the end we look for") - require.Equal(t, refB, eq.Progress().Origin, "Expecting to be set back derivation L1 progress to B") + require.Equal(t, refB, eq.Origin(), "Expecting to be set back derivation L1 progress to B") require.Equal(t, refA1, eq.Finalized(), "A1 is recognized as finalized before we run any steps") // now say C1 was included in D and became the new safe head - eq.progress.Origin = refD + eq.origin = refD prev.origin = refD eq.safeHead = refC1 eq.postProcessSafeL2() // now say D0 was included in E and became the new safe head - eq.progress.Origin = refE + eq.origin = refE prev.origin = refE eq.safeHead = refD0 eq.postProcessSafeL2() diff --git a/op-node/rollup/derive/engine_update.go b/op-node/rollup/derive/engine_update.go index 0f37052e7fc00..2bbfe7ed93935 100644 --- a/op-node/rollup/derive/engine_update.go +++ b/op-node/rollup/derive/engine_update.go @@ -5,9 +5,10 @@ import ( "errors" "fmt" - "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-node/eth" ) // isDepositTx checks an opaqueTx to determine if it is a Deposit Transaction @@ -68,9 +69,13 @@ func sanityCheckPayload(payload *eth.ExecutionPayload) error { type BlockInsertionErrType uint const ( + // BlockInsertOK indicates that the payload was successfully executed and appended to the canonical chain. BlockInsertOK BlockInsertionErrType = iota + // BlockInsertTemporaryErr indicates that the insertion failed but may succeed at a later time without changes to the payload. BlockInsertTemporaryErr + // BlockInsertPrestateErr indicates that the pre-state to insert the payload could not be prepared, e.g. due to missing chain data. BlockInsertPrestateErr + // BlockInsertPayloadErr indicates that the payload was invalid and cannot become canonical. BlockInsertPayloadErr ) @@ -80,37 +85,53 @@ const ( // If updateSafe is true, the head block is considered to be the safe head as well as the head. // It returns the payload, an RPC error (if the payload might still be valid), and a payload error (if the payload was not valid) func InsertHeadBlock(ctx context.Context, log log.Logger, eng Engine, fc eth.ForkchoiceState, attrs *eth.PayloadAttributes, updateSafe bool) (out *eth.ExecutionPayload, errTyp BlockInsertionErrType, err error) { + id, errTyp, err := StartPayload(ctx, eng, fc, attrs) + if err != nil { + return nil, errTyp, err + } + return ConfirmPayload(ctx, log, eng, fc, id, updateSafe) +} + +// StartPayload starts an execution payload building process in the provided Engine, with the given attributes. +// The severity of the error is distinguished to determine whether the same payload attributes may be re-attempted later. +func StartPayload(ctx context.Context, eng Engine, fc eth.ForkchoiceState, attrs *eth.PayloadAttributes) (id eth.PayloadID, errType BlockInsertionErrType, err error) { fcRes, err := eng.ForkchoiceUpdate(ctx, &fc, attrs) if err != nil { var inputErr eth.InputError if errors.As(err, &inputErr) { switch inputErr.Code { case eth.InvalidForkchoiceState: - return nil, BlockInsertPrestateErr, fmt.Errorf("pre-block-creation forkchoice update was inconsistent with engine, need reset to resolve: %w", inputErr.Unwrap()) + return eth.PayloadID{}, BlockInsertPrestateErr, fmt.Errorf("pre-block-creation forkchoice update was inconsistent with engine, need reset to resolve: %w", inputErr.Unwrap()) case eth.InvalidPayloadAttributes: - return nil, BlockInsertPayloadErr, fmt.Errorf("payload attributes are not valid, cannot build block: %w", inputErr.Unwrap()) + return eth.PayloadID{}, BlockInsertPayloadErr, fmt.Errorf("payload attributes are not valid, cannot build block: %w", inputErr.Unwrap()) default: - return nil, BlockInsertPrestateErr, fmt.Errorf("unexpected error code in forkchoice-updated response: %w", err) + return eth.PayloadID{}, BlockInsertPrestateErr, fmt.Errorf("unexpected error code in forkchoice-updated response: %w", err) } } else { - return nil, BlockInsertTemporaryErr, fmt.Errorf("failed to create new block via forkchoice: %w", err) + return eth.PayloadID{}, BlockInsertTemporaryErr, fmt.Errorf("failed to create new block via forkchoice: %w", err) } } switch fcRes.PayloadStatus.Status { // TODO(proto): snap sync - specify explicit different error type if node is syncing case eth.ExecutionInvalid, eth.ExecutionInvalidBlockHash: - return nil, BlockInsertPayloadErr, eth.ForkchoiceUpdateErr(fcRes.PayloadStatus) + return eth.PayloadID{}, BlockInsertPayloadErr, eth.ForkchoiceUpdateErr(fcRes.PayloadStatus) case eth.ExecutionValid: - break + id := fcRes.PayloadID + if id == nil { + return eth.PayloadID{}, BlockInsertTemporaryErr, errors.New("nil id in forkchoice result when expecting a valid ID") + } + return *id, BlockInsertOK, nil default: - return nil, BlockInsertTemporaryErr, eth.ForkchoiceUpdateErr(fcRes.PayloadStatus) + return eth.PayloadID{}, BlockInsertTemporaryErr, eth.ForkchoiceUpdateErr(fcRes.PayloadStatus) } - id := fcRes.PayloadID - if id == nil { - return nil, BlockInsertTemporaryErr, errors.New("nil id in forkchoice result when expecting a valid ID") - } - payload, err := eng.GetPayload(ctx, *id) +} + +// ConfirmPayload ends an execution payload building process in the provided Engine, and persists the payload as the canonical head. +// If updateSafe is true, then the payload will also be recognized as safe-head at the same time. +// The severity of the error is distinguished to determine whether the payload was valid and can become canonical. +func ConfirmPayload(ctx context.Context, log log.Logger, eng Engine, fc eth.ForkchoiceState, id eth.PayloadID, updateSafe bool) (out *eth.ExecutionPayload, errTyp BlockInsertionErrType, err error) { + payload, err := eng.GetPayload(ctx, id) if err != nil { // even if it is an input-error (unknown payload ID), it is temporary, since we will re-attempt the full payload building, not just the retrieval of the payload. return nil, BlockInsertTemporaryErr, fmt.Errorf("failed to get execution payload: %w", err) @@ -134,7 +155,7 @@ func InsertHeadBlock(ctx context.Context, log log.Logger, eng Engine, fc eth.For if updateSafe { fc.SafeBlockHash = payload.BlockHash } - fcRes, err = eng.ForkchoiceUpdate(ctx, &fc, nil) + fcRes, err := eng.ForkchoiceUpdate(ctx, &fc, nil) if err != nil { var inputErr eth.InputError if errors.As(err, &inputErr) { diff --git a/op-node/rollup/derive/fuzz_parsers_test.go b/op-node/rollup/derive/fuzz_parsers_test.go index 9fd047feca50c..5dddea53138fa 100644 --- a/op-node/rollup/derive/fuzz_parsers_test.go +++ b/op-node/rollup/derive/fuzz_parsers_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-node/testutils" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -40,14 +41,6 @@ func BytesToBigInt(b []byte) *big.Int { return new(big.Int).SetBytes(cap_byte_slice(b, 32)) } -func BigEqual(a, b *big.Int) bool { - if a == nil || b == nil { - return a == b - } else { - return a.Cmp(b) == 0 - } -} - // FuzzL1InfoRoundTrip checks that our encoder round trips properly func FuzzL1InfoRoundTrip(f *testing.F) { f.Fuzz(func(t *testing.T, number, time uint64, baseFee, hash []byte, seqNumber uint64) { @@ -67,7 +60,7 @@ func FuzzL1InfoRoundTrip(f *testing.F) { if err != nil { t.Fatalf("Failed to unmarshal binary: %v", err) } - if !cmp.Equal(in, out, cmp.Comparer(BigEqual)) { + if !cmp.Equal(in, out, cmp.Comparer(testutils.BigEqual)) { t.Fatalf("The data did not round trip correctly. in: %v. out: %v", in, out) } @@ -120,7 +113,7 @@ func FuzzL1InfoAgainstContract(f *testing.F) { t.Fatalf("Failed to unmarshal binary: %v", err) } - if !cmp.Equal(expected, actual, cmp.Comparer(BigEqual)) { + if !cmp.Equal(expected, actual, cmp.Comparer(testutils.BigEqual)) { t.Fatalf("The data did not round trip correctly. expected: %v. actual: %v", expected, actual) } @@ -266,7 +259,7 @@ func FuzzUnmarshallLogEvent(f *testing.F) { reconstructed.To = *dep.To } - if !cmp.Equal(depositEvent, reconstructed, cmp.Comparer(BigEqual)) { + if !cmp.Equal(depositEvent, reconstructed, cmp.Comparer(testutils.BigEqual)) { t.Fatalf("The deposit tx did not match. tx: %v. actual: %v", reconstructed, depositEvent) } @@ -279,7 +272,7 @@ func FuzzUnmarshallLogEvent(f *testing.F) { OpaqueData: opaqueData, Raw: types.Log{}, } - if !cmp.Equal(depositEvent, inputArgs, cmp.Comparer(BigEqual)) { + if !cmp.Equal(depositEvent, inputArgs, cmp.Comparer(testutils.BigEqual)) { t.Fatalf("The input args did not match. input: %v. actual: %v", inputArgs, depositEvent) } }) diff --git a/op-node/rollup/derive/l1_block_info.go b/op-node/rollup/derive/l1_block_info.go index a53387c54d00b..7564131298be0 100644 --- a/op-node/rollup/derive/l1_block_info.go +++ b/op-node/rollup/derive/l1_block_info.go @@ -40,6 +40,10 @@ func (info *L1BlockInfo) MarshalBinary() ([]byte, error) { offset += 32 binary.BigEndian.PutUint64(data[offset+24:offset+32], info.Time) offset += 32 + // Ensure that the baseFee is not too large. + if info.BaseFee.BitLen() > 256 { + return nil, fmt.Errorf("base fee exceeds 256 bits: %d", info.BaseFee) + } info.BaseFee.FillBytes(data[offset : offset+32]) offset += 32 copy(data[offset:offset+32], info.BlockHash.Bytes()) diff --git a/op-node/rollup/derive/l1_retrieval.go b/op-node/rollup/derive/l1_retrieval.go index dda4be6434bac..1fd4acf8cb54b 100644 --- a/op-node/rollup/derive/l1_retrieval.go +++ b/op-node/rollup/derive/l1_retrieval.go @@ -25,7 +25,7 @@ type L1Retrieval struct { datas DataIter } -var _ PullStage = (*L1Retrieval)(nil) +var _ ResetableStage = (*L1Retrieval)(nil) func NewL1Retrieval(log log.Logger, dataSrc DataAvailabilitySource, prev NextBlockProvider) *L1Retrieval { return &L1Retrieval{ diff --git a/op-node/rollup/derive/l1_traversal.go b/op-node/rollup/derive/l1_traversal.go index db19eed5a94db..8ad65873e9ee8 100644 --- a/op-node/rollup/derive/l1_traversal.go +++ b/op-node/rollup/derive/l1_traversal.go @@ -24,7 +24,7 @@ type L1Traversal struct { log log.Logger } -var _ PullStage = (*L1Traversal)(nil) +var _ ResetableStage = (*L1Traversal)(nil) func NewL1Traversal(log log.Logger, l1Blocks L1BlockRefByNumberFetcher) *L1Traversal { return &L1Traversal{ diff --git a/op-node/rollup/derive/pipeline.go b/op-node/rollup/derive/pipeline.go index bc8fe63d78009..2d34c8d2ddb43 100644 --- a/op-node/rollup/derive/pipeline.go +++ b/op-node/rollup/derive/pipeline.go @@ -24,46 +24,22 @@ type L1Fetcher interface { L1TransactionFetcher } -type StageProgress interface { - Progress() Progress -} - -type PullStage interface { +type ResetableStage interface { // Reset resets a pull stage. `base` refers to the L1 Block Reference to reset to. - // TODO: Return L1 Block reference Reset(ctx context.Context, base eth.L1BlockRef) error } -type Stage interface { - StageProgress - - // Step tries to progress the state. - // The outer stage progress informs the step what to do. - // - // If the stage: - // - returns EOF: the stage will be skipped - // - returns another error: the stage will make the pipeline error. - // - returns nil: the stage will be repeated next Step - Step(ctx context.Context, outer Progress) error - - // ResetStep prepares the state for usage in regular steps. - // Similar to Step(ctx) it returns: - // - EOF if the next stage should be reset - // - error if the reset should start all over again - // - nil if the reset should continue resetting this stage. - ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error -} - type EngineQueueStage interface { Finalized() eth.L2BlockRef UnsafeL2Head() eth.L2BlockRef SafeL2Head() eth.L2BlockRef - Progress() Progress + Origin() eth.L1BlockRef SetUnsafeHead(head eth.L2BlockRef) Finalize(l1Origin eth.BlockID) AddSafeAttributes(attributes *eth.PayloadAttributes) AddUnsafePayload(payload *eth.ExecutionPayload) + Step(context.Context) error } // DerivationPipeline is updated with new L1 data, and the Step() function can be iterated on to keep the L2 Engine in sync. @@ -74,19 +50,12 @@ type DerivationPipeline struct { // Index of the stage that is currently being reset. // >= len(stages) if no additional resetting is required - resetting int - pullResetIdx int - - // Index of the stage that is currently being processed. - active int + resetting int + stages []ResetableStage - // stages in execution order. A stage Step that: - stages []Stage - - pullStages []PullStage - traversal *L1Traversal - - eng EngineQueueStage + // Special stages to keep track of + traversal *L1Traversal + eng EngineQueueStage metrics Metrics } @@ -103,33 +72,32 @@ func NewDerivationPipeline(log log.Logger, cfg *rollup.Config, l1Fetcher L1Fetch batchQueue := NewBatchQueue(log, cfg, chInReader) attributesQueue := NewAttributesQueue(log, cfg, l1Fetcher, batchQueue) - // Push stages (that act like pull stages b/c we push from the innermost stages prior to the outermost stages) - eng := NewEngineQueue(log, cfg, engine, metrics, attributesQueue) + // Step stages + eng := NewEngineQueue(log, cfg, engine, metrics, attributesQueue, l1Fetcher) - stages := []Stage{eng} - pullStages := []PullStage{attributesQueue, batchQueue, chInReader, bank, l1Src, l1Traversal} + // Reset from engine queue then up from L1 Traversal. The stages do not talk to each other during + // the reset, but after the engine queue, this is the order in which the stages could talk to each other. + // Note: The engine queue stage is the only reset that can fail. + stages := []ResetableStage{eng, l1Traversal, l1Src, bank, chInReader, batchQueue, attributesQueue} return &DerivationPipeline{ - log: log, - cfg: cfg, - l1Fetcher: l1Fetcher, - resetting: 0, - active: 0, - stages: stages, - pullStages: pullStages, - eng: eng, - metrics: metrics, - traversal: l1Traversal, + log: log, + cfg: cfg, + l1Fetcher: l1Fetcher, + resetting: 0, + stages: stages, + eng: eng, + metrics: metrics, + traversal: l1Traversal, } } func (dp *DerivationPipeline) Reset() { dp.resetting = 0 - dp.pullResetIdx = 0 } -func (dp *DerivationPipeline) Progress() Progress { - return dp.eng.Progress() +func (dp *DerivationPipeline) Origin() eth.L1BlockRef { + return dp.eng.Origin() } func (dp *DerivationPipeline) Finalize(l1Origin eth.BlockID) { @@ -165,12 +133,12 @@ func (dp *DerivationPipeline) AddUnsafePayload(payload *eth.ExecutionPayload) { // An error is expected when the underlying source closes. // When Step returns nil, it should be called again, to continue the derivation process. func (dp *DerivationPipeline) Step(ctx context.Context) error { - defer dp.metrics.RecordL1Ref("l1_derived", dp.Progress().Origin) + defer dp.metrics.RecordL1Ref("l1_derived", dp.Origin()) // if any stages need to be reset, do that first. if dp.resetting < len(dp.stages) { - if err := dp.stages[dp.resetting].ResetStep(ctx, dp.l1Fetcher); err == io.EOF { - dp.log.Debug("reset of stage completed", "stage", dp.resetting, "origin", dp.stages[dp.resetting].Progress().Origin) + if err := dp.stages[dp.resetting].Reset(ctx, dp.eng.Origin()); err == io.EOF { + dp.log.Debug("reset of stage completed", "stage", dp.resetting, "origin", dp.eng.Origin()) dp.resetting += 1 return nil } else if err != nil { @@ -179,37 +147,14 @@ func (dp *DerivationPipeline) Step(ctx context.Context) error { return nil } } - // Then reset the pull based stages - if dp.pullResetIdx < len(dp.pullStages) { - // Use the last stage's progress as the one to pull from - inner := dp.stages[len(dp.stages)-1].Progress() - - // Do the reset - if err := dp.pullStages[dp.pullResetIdx].Reset(ctx, inner.Origin); err == io.EOF { - // dp.log.Debug("reset of stage completed", "stage", dp.pullResetIdx, "origin", dp.pullStages[dp.pullResetIdx].Progress().Origin) - dp.pullResetIdx += 1 - return nil - } else if err != nil { - return fmt.Errorf("stage %d failed resetting: %w", dp.pullResetIdx, err) - } else { - return nil - } - } - // Lastly advance the stages - for i, stage := range dp.stages { - var outer Progress - if i+1 < len(dp.stages) { - outer = dp.stages[i+1].Progress() - } - if err := stage.Step(ctx, outer); err == io.EOF { - continue - } else if err != nil { - return fmt.Errorf("stage %d failed: %w", i, err) - } else { - return nil - } + // Now step the engine queue. It will pull earlier data as needed. + if err := dp.eng.Step(ctx); err == io.EOF { + // If every stage has returned io.EOF, try to advance the L1 Origin + return dp.traversal.AdvanceL1Block(ctx) + } else if err != nil { + return fmt.Errorf("engine stage failed: %w", err) + } else { + return nil } - // If every stage has returned io.EOF, try to advance the L1 Origin - return dp.traversal.AdvanceL1Block(ctx) } diff --git a/op-node/rollup/derive/pipeline_test.go b/op-node/rollup/derive/pipeline_test.go index 427fb16760051..995b479a695dc 100644 --- a/op-node/rollup/derive/pipeline_test.go +++ b/op-node/rollup/derive/pipeline_test.go @@ -1,89 +1,9 @@ package derive -import ( - "context" - "io" - "testing" - - "github.com/stretchr/testify/mock" - - "github.com/ethereum-optimism/optimism/op-node/eth" - "github.com/ethereum-optimism/optimism/op-node/testutils" -) +import "github.com/ethereum-optimism/optimism/op-node/testutils" var _ Engine = (*testutils.MockEngine)(nil) var _ L1Fetcher = (*testutils.MockL1Source)(nil) -type MockOriginStage struct { - mock.Mock - progress Progress -} - -func (m *MockOriginStage) Progress() Progress { - return m.progress -} - -var _ StageProgress = (*MockOriginStage)(nil) - -// RepeatResetStep is a test util that will repeat the ResetStep function until an error. -// If the step runs too many times, it will fail the test. -func RepeatResetStep(t *testing.T, step func(ctx context.Context, l1Fetcher L1Fetcher) error, l1Fetcher L1Fetcher, max int) error { - ctx := context.Background() - for i := 0; i < max; i++ { - err := step(ctx, l1Fetcher) - if err == io.EOF { - return nil - } - if err != nil { - return err - } - } - t.Fatal("ran out of steps") - return nil -} - -// RepeatStep is a test util that will repeat the Step function until an error. -// If the step runs too many times, it will fail the test. -func RepeatStep(t *testing.T, step func(ctx context.Context, outer Progress) error, outer Progress, max int) error { - ctx := context.Background() - for i := 0; i < max; i++ { - err := step(ctx, outer) - if err == io.EOF { - return nil - } - if err != nil { - return err - } - } - t.Fatal("ran out of steps") - return nil -} - -// TestMetrics implements the metrics used in the derivation pipeline as no-op operations. -// Optionally a test may hook into the metrics -type TestMetrics struct { - recordL1Ref func(name string, ref eth.L1BlockRef) - recordL2Ref func(name string, ref eth.L2BlockRef) - recordUnsafePayloads func(length uint64, memSize uint64, next eth.BlockID) -} - -func (t *TestMetrics) RecordL1Ref(name string, ref eth.L1BlockRef) { - if t.recordL1Ref != nil { - t.recordL1Ref(name, ref) - } -} - -func (t *TestMetrics) RecordL2Ref(name string, ref eth.L2BlockRef) { - if t.recordL2Ref != nil { - t.recordL2Ref(name, ref) - } -} - -func (t *TestMetrics) RecordUnsafePayloadsBuffer(length uint64, memSize uint64, next eth.BlockID) { - if t.recordUnsafePayloads != nil { - t.recordUnsafePayloads(length, memSize, next) - } -} - -var _ Metrics = (*TestMetrics)(nil) +var _ Metrics = (*testutils.TestDerivationMetrics)(nil) diff --git a/op-node/rollup/derive/progress.go b/op-node/rollup/derive/progress.go deleted file mode 100644 index b6915b998548b..0000000000000 --- a/op-node/rollup/derive/progress.go +++ /dev/null @@ -1,46 +0,0 @@ -package derive - -import ( - "fmt" - - "github.com/ethereum-optimism/optimism/op-node/eth" -) - -// Progress represents the progress of a derivation stage: -// the input L1 block that is being processed, and whether it's fully processed yet. -type Progress struct { - Origin eth.L1BlockRef - // Closed means that the Current has no more data that the stage may need. - Closed bool -} - -func (pr *Progress) Update(outer Progress) (changed bool, err error) { - if outer.Origin.Number < pr.Origin.Number { - return false, nil - } - if pr.Closed { - if outer.Closed { - if pr.Origin.ID() != outer.Origin.ID() { - return true, NewResetError(fmt.Errorf("outer stage changed origin from %s to %s without opening it", pr.Origin, outer.Origin)) - } - return false, nil - } else { - if pr.Origin.Hash != outer.Origin.ParentHash { - return true, NewResetError(fmt.Errorf("detected internal pipeline reorg of L1 origin data from %s to %s", pr.Origin, outer.Origin)) - } - pr.Origin = outer.Origin - pr.Closed = false - return true, nil - } - } else { - if pr.Origin.ID() != outer.Origin.ID() { - return true, NewResetError(fmt.Errorf("outer stage changed origin from %s to %s before closing it", pr.Origin, outer.Origin)) - } - if outer.Closed { - pr.Closed = true - return true, nil - } else { - return false, nil - } - } -} diff --git a/op-node/rollup/driver/driver.go b/op-node/rollup/driver/driver.go index ad21915d3e9e7..8fac03ffb7eaa 100644 --- a/op-node/rollup/driver/driver.go +++ b/op-node/rollup/driver/driver.go @@ -3,18 +3,14 @@ package driver import ( "context" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" ) -type Driver struct { - s *state -} - type Metrics interface { RecordPipelineReset() RecordSequencingError() @@ -34,11 +30,6 @@ type Metrics interface { CountSequencedTxs(count int) } -type Downloader interface { - InfoByHash(ctx context.Context, hash common.Hash) (eth.BlockInfo, error) - Fetch(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, eth.ReceiptsFetcher, error) -} - type L1Chain interface { derive.L1Fetcher L1BlockRefByLabel(context.Context, eth.BlockLabel) (eth.L1BlockRef, error) @@ -59,61 +50,64 @@ type DerivationPipeline interface { Finalized() eth.L2BlockRef SafeL2Head() eth.L2BlockRef UnsafeL2Head() eth.L2BlockRef - Progress() derive.Progress -} - -type outputInterface interface { - // createNewBlock builds a new block based on the L2 Head, L1 Origin, and the current mempool. - createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *eth.ExecutionPayload, error) -} - -type Network interface { - // PublishL2Payload is called by the driver whenever there is a new payload to publish, synchronously with the driver main loop. - PublishL2Payload(ctx context.Context, payload *eth.ExecutionPayload) error + Origin() eth.L1BlockRef } -func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, network Network, log log.Logger, snapshotLog log.Logger, metrics Metrics) *Driver { - output := &outputImpl{ - Config: cfg, - dl: l1, - l2: l2, - log: log, - } - - var state *state - verifConfDepth := NewConfDepth(driverCfg.VerifierConfDepth, func() eth.L1BlockRef { return state.l1Head }, l1) - derivationPipeline := derive.NewDerivationPipeline(log, cfg, verifConfDepth, l2, metrics) - state = NewState(driverCfg, log, snapshotLog, cfg, l1, l2, output, derivationPipeline, network, metrics) - return &Driver{s: state} -} +type L1StateIface interface { + HandleNewL1HeadBlock(head eth.L1BlockRef) + HandleNewL1SafeBlock(safe eth.L1BlockRef) + HandleNewL1FinalizedBlock(finalized eth.L1BlockRef) -func (d *Driver) OnL1Head(ctx context.Context, head eth.L1BlockRef) error { - return d.s.OnL1Head(ctx, head) + L1Head() eth.L1BlockRef + L1Safe() eth.L1BlockRef + L1Finalized() eth.L1BlockRef } -func (d *Driver) OnL1Safe(ctx context.Context, safe eth.L1BlockRef) error { - return d.s.OnL1Safe(ctx, safe) +type L1OriginSelectorIface interface { + FindL1Origin(ctx context.Context, l1Head eth.L1BlockRef, l2Head eth.L2BlockRef) (eth.L1BlockRef, error) } -func (d *Driver) OnL1Finalized(ctx context.Context, finalized eth.L1BlockRef) error { - return d.s.OnL1Finalized(ctx, finalized) -} +type SequencerIface interface { + StartBuildingBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) error + CompleteBuildingBlock(ctx context.Context) (*eth.ExecutionPayload, error) -func (d *Driver) OnUnsafeL2Payload(ctx context.Context, payload *eth.ExecutionPayload) error { - return d.s.OnUnsafeL2Payload(ctx, payload) + // createNewBlock builds a new block based on the L2 Head, L1 Origin, and the current mempool. + CreateNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *eth.ExecutionPayload, error) } -func (d *Driver) ResetDerivationPipeline(ctx context.Context) error { - return d.s.ResetDerivationPipeline(ctx) +type Network interface { + // PublishL2Payload is called by the driver whenever there is a new payload to publish, synchronously with the driver main loop. + PublishL2Payload(ctx context.Context, payload *eth.ExecutionPayload) error } -func (d *Driver) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) { - return d.s.SyncStatus(ctx) -} +// NewDriver composes an events handler that tracks L1 state, triggers L2 derivation, and optionally sequences new L2 blocks. +func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, network Network, log log.Logger, snapshotLog log.Logger, metrics Metrics) *Driver { + sequencer := NewSequencer(log, cfg, l1, l2) + l1State := NewL1State(log, metrics) + findL1Origin := NewL1OriginSelector(log, cfg, l1, driverCfg.SequencerConfDepth) + verifConfDepth := NewConfDepth(driverCfg.VerifierConfDepth, l1State.L1Head, l1) + derivationPipeline := derive.NewDerivationPipeline(log, cfg, verifConfDepth, l2, metrics) -func (d *Driver) Start(ctx context.Context) error { - return d.s.Start(ctx) -} -func (d *Driver) Close() error { - return d.s.Close() + return &Driver{ + l1State: l1State, + derivation: derivationPipeline, + idleDerivation: false, + syncStatusReq: make(chan chan eth.SyncStatus, 10), + forceReset: make(chan chan struct{}, 10), + config: cfg, + driverConfig: driverCfg, + done: make(chan struct{}), + log: log, + snapshotLog: snapshotLog, + l1: l1, + l2: l2, + l1OriginSelector: findL1Origin, + sequencer: sequencer, + network: network, + metrics: metrics, + l1HeadSig: make(chan eth.L1BlockRef, 10), + l1SafeSig: make(chan eth.L1BlockRef, 10), + l1FinalizedSig: make(chan eth.L1BlockRef, 10), + unsafeL2Payloads: make(chan *eth.ExecutionPayload, 10), + } } diff --git a/op-node/rollup/driver/l1_state.go b/op-node/rollup/driver/l1_state.go new file mode 100644 index 0000000000000..9b845ebb82640 --- /dev/null +++ b/op-node/rollup/driver/l1_state.go @@ -0,0 +1,76 @@ +package driver + +import ( + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-node/eth" +) + +type L1Metrics interface { + RecordL1ReorgDepth(d uint64) + RecordL1Ref(name string, ref eth.L1BlockRef) +} + +// L1State tracks L1 head, safe and finalized blocks. It is not safe to write and read concurrently. +type L1State struct { + log log.Logger + metrics L1Metrics + + // Latest recorded head, safe block and finalized block of the L1 Chain, independent of derivation work + l1Head eth.L1BlockRef + l1Safe eth.L1BlockRef + l1Finalized eth.L1BlockRef +} + +func NewL1State(log log.Logger, metrics L1Metrics) *L1State { + return &L1State{ + log: log, + metrics: metrics, + } +} + +func (s *L1State) HandleNewL1HeadBlock(head eth.L1BlockRef) { + // We don't need to do anything if the head hasn't changed. + if s.l1Head == (eth.L1BlockRef{}) { + s.log.Info("Received first L1 head signal", "l1_head", head) + } else if s.l1Head.Hash == head.Hash { + s.log.Trace("Received L1 head signal that is the same as the current head", "l1_head", head) + } else if s.l1Head.Hash == head.ParentHash { + // We got a new L1 block whose parent hash is the same as the current L1 head. Means we're + // dealing with a linear extension (new block is the immediate child of the old one). + s.log.Debug("L1 head moved forward", "l1_head", head) + } else { + if s.l1Head.Number >= head.Number { + s.metrics.RecordL1ReorgDepth(s.l1Head.Number - head.Number) + } + // New L1 block is not the same as the current head or a single step linear extension. + // This could either be a long L1 extension, or a reorg, or we simply missed a head update. + s.log.Warn("L1 head signal indicates a possible L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", head.ParentHash, "new_l1_head", head) + } + s.metrics.RecordL1Ref("l1_head", head) + s.l1Head = head +} + +func (s *L1State) HandleNewL1SafeBlock(safe eth.L1BlockRef) { + s.log.Info("New L1 safe block", "l1_safe", safe) + s.metrics.RecordL1Ref("l1_safe", safe) + s.l1Safe = safe +} + +func (s *L1State) HandleNewL1FinalizedBlock(finalized eth.L1BlockRef) { + s.log.Info("New L1 finalized block", "l1_finalized", finalized) + s.metrics.RecordL1Ref("l1_finalized", finalized) + s.l1Finalized = finalized +} + +func (s *L1State) L1Head() eth.L1BlockRef { + return s.l1Head +} + +func (s *L1State) L1Safe() eth.L1BlockRef { + return s.l1Safe +} + +func (s *L1State) L1Finalized() eth.L1BlockRef { + return s.l1Finalized +} diff --git a/op-node/rollup/driver/origin_selector.go b/op-node/rollup/driver/origin_selector.go new file mode 100644 index 0000000000000..0b83e7087ff46 --- /dev/null +++ b/op-node/rollup/driver/origin_selector.go @@ -0,0 +1,79 @@ +package driver + +import ( + "context" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" +) + +type L1Blocks interface { + derive.L1BlockRefByHashFetcher + derive.L1BlockRefByNumberFetcher +} + +type L1OriginSelector struct { + log log.Logger + cfg *rollup.Config + + l1 L1Blocks + sequencingConfDepth uint64 +} + +func NewL1OriginSelector(log log.Logger, cfg *rollup.Config, l1 L1Blocks, sequencingConfDepth uint64) *L1OriginSelector { + return &L1OriginSelector{ + log: log, + cfg: cfg, + l1: l1, + sequencingConfDepth: sequencingConfDepth, + } +} + +// FindL1Origin determines what the next L1 Origin should be. +// The L1 Origin is either the L2 Head's Origin, or the following L1 block +// if the next L2 block's time is greater than or equal to the L2 Head's Origin. +func (los *L1OriginSelector) FindL1Origin(ctx context.Context, l1Head eth.L1BlockRef, l2Head eth.L2BlockRef) (eth.L1BlockRef, error) { + // If we are at the head block, don't do a lookup. + if l2Head.L1Origin.Hash == l1Head.Hash { + return l1Head, nil + } + + // Grab a reference to the current L1 origin block. + currentOrigin, err := los.l1.L1BlockRefByHash(ctx, l2Head.L1Origin.Hash) + if err != nil { + return eth.L1BlockRef{}, err + } + + if currentOrigin.Number+1+los.sequencingConfDepth > l1Head.Number { + // TODO: we can decide to ignore confirmation depth if we would be forced + // to make an empty block (only deposits) by staying on the current origin. + log.Info("sequencing with old origin to preserve conf depth", + "current", currentOrigin, "current_time", currentOrigin.Time, + "l1_head", l1Head, "l1_head_time", l1Head.Time, + "l2_head", l2Head, "l2_head_time", l2Head.Time, + "depth", los.sequencingConfDepth) + return currentOrigin, nil + } + + // Attempt to find the next L1 origin block, where the next origin is the immediate child of + // the current origin block. + nextOrigin, err := los.l1.L1BlockRefByNumber(ctx, currentOrigin.Number+1) + if err != nil { + log.Error("Failed to get next origin. Falling back to current origin", "err", err) + return currentOrigin, nil + } + + // If the next L2 block time is greater than the next origin block's time, we can choose to + // start building on top of the next origin. Sequencer implementation has some leeway here and + // could decide to continue to build on top of the previous origin until the Sequencer runs out + // of slack. For simplicity, we implement our Sequencer to always start building on the latest + // L1 block when we can. + if l2Head.Time+los.cfg.BlockTime >= nextOrigin.Time { + return nextOrigin, nil + } + + return currentOrigin, nil +} diff --git a/op-node/rollup/driver/sequencer.go b/op-node/rollup/driver/sequencer.go new file mode 100644 index 0000000000000..2c45b7e396692 --- /dev/null +++ b/op-node/rollup/driver/sequencer.go @@ -0,0 +1,112 @@ +package driver + +import ( + "context" + "fmt" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" +) + +type Downloader interface { + InfoByHash(ctx context.Context, hash common.Hash) (eth.BlockInfo, error) + FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) +} + +// Sequencer implements the sequencing interface of the driver: it starts and completes block building jobs. +type Sequencer struct { + log log.Logger + config *rollup.Config + + l1 Downloader + l2 derive.Engine + + buildingOnto eth.ForkchoiceState + buildingID eth.PayloadID +} + +func NewSequencer(log log.Logger, cfg *rollup.Config, l1 Downloader, l2 derive.Engine) *Sequencer { + return &Sequencer{ + log: log, + config: cfg, + l1: l1, + l2: l2, + } +} + +// StartBuildingBlock initiates a block building job on top of the given L2 head, safe and finalized blocks, and using the provided l1Origin. +func (d *Sequencer) StartBuildingBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) error { + d.log.Info("creating new block", "parent", l2Head, "l1Origin", l1Origin) + if d.buildingID != (eth.PayloadID{}) { // This may happen when we decide to build a different block in response to a reorg. Or when previous block building failed. + d.log.Warn("did not finish previous block building, starting new building now", "prev_onto", d.buildingOnto.HeadBlockHash, "prev_payload_id", d.buildingID, "new_onto", l2Head) + } + + fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) + defer cancel() + + attrs, err := derive.PreparePayloadAttributes(fetchCtx, d.config, d.l1, l2Head, l2Head.Time+d.config.BlockTime, l1Origin.ID()) + if err != nil { + return err + } + + // If our next L2 block timestamp is beyond the Sequencer drift threshold, then we must produce + // empty blocks (other than the L1 info deposit and any user deposits). We handle this by + // setting NoTxPool to true, which will cause the Sequencer to not include any transactions + // from the transaction pool. + attrs.NoTxPool = uint64(attrs.Timestamp) >= l1Origin.Time+d.config.MaxSequencerDrift + + // And construct our fork choice state. This is our current fork choice state and will be + // updated as a result of executing the block based on the attributes described above. + fc := eth.ForkchoiceState{ + HeadBlockHash: l2Head.Hash, + SafeBlockHash: l2SafeHead.Hash, + FinalizedBlockHash: l2Finalized.Hash, + } + // Start a payload building process. + id, errTyp, err := derive.StartPayload(ctx, d.l2, fc, attrs) + if err != nil { + return fmt.Errorf("failed to start building on top of L2 chain %s, error (%d): %w", l2Head, errTyp, err) + } + d.buildingOnto = fc + d.buildingID = id + return nil +} + +// CompleteBuildingBlock takes the current block that is being built, and asks the engine to complete the building, seal the block, and persist it as canonical. +// Warning: the safe and finalized L2 blocks as viewed during the initiation of the block building are reused for completion of the block building. +// The Execution engine should not change the safe and finalized blocks between start and completion of block building. +func (d *Sequencer) CompleteBuildingBlock(ctx context.Context) (*eth.ExecutionPayload, error) { + if d.buildingID == (eth.PayloadID{}) { + return nil, fmt.Errorf("cannot complete payload building: not currently building a payload") + } + + // Actually execute the block and add it to the head of the chain. + payload, errTyp, err := derive.ConfirmPayload(ctx, d.log, d.l2, d.buildingOnto, d.buildingID, false) + if err != nil { + return nil, fmt.Errorf("failed to complete building on top of L2 chain %s, error (%d): %w", d.buildingOnto.HeadBlockHash, errTyp, err) + } + return payload, nil +} + +// CreateNewBlock sequences a L2 block with immediate building and sealing. +func (d *Sequencer) CreateNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *eth.ExecutionPayload, error) { + if err := d.StartBuildingBlock(ctx, l2Head, l2SafeHead, l2Finalized, l1Origin); err != nil { + return l2Head, nil, err + } + payload, err := d.CompleteBuildingBlock(ctx) + if err != nil { + return l2Head, nil, err + } + d.buildingID = eth.PayloadID{} + + // Generate an L2 block ref from the payload. + ref, err := derive.PayloadToBlockRef(payload, &d.config.Genesis) + + return ref, payload, err +} diff --git a/op-node/rollup/driver/state.go b/op-node/rollup/driver/state.go index 3538cb6d8344f..925a8dd75efee 100644 --- a/op-node/rollup/driver/state.go +++ b/op-node/rollup/driver/state.go @@ -9,21 +9,19 @@ import ( gosync "sync" "time" - "github.com/ethereum-optimism/optimism/op-node/backoff" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-service/backoff" ) // Deprecated: use eth.SyncStatus instead. type SyncStatus = eth.SyncStatus -type state struct { - // Latest recorded head, safe block and finalized block of the L1 Chain, independent of derivation work - l1Head eth.L1BlockRef - l1Safe eth.L1BlockRef - l1Finalized eth.L1BlockRef +type Driver struct { + l1State L1StateIface // The derivation pipeline is reset whenever we reorg. // The derivation pipeline determines the new l2Safe. @@ -40,10 +38,10 @@ type state struct { forceReset chan chan struct{} // Rollup config: rollup chain configuration - Config *rollup.Config + config *rollup.Config // Driver config: verifier and sequencer settings - DriverConfig *Config + driverConfig *Config // L1 Signals: // @@ -58,10 +56,11 @@ type state struct { // L2 Signals: unsafeL2Payloads chan *eth.ExecutionPayload - l1 L1Chain - l2 L2Chain - output outputInterface - network Network // may be nil, network for is optional + l1 L1Chain + l2 L2Chain + l1OriginSelector L1OriginSelectorIface + sequencer SequencerIface + network Network // may be nil, network for is optional metrics Metrics log log.Logger @@ -71,35 +70,9 @@ type state struct { wg gosync.WaitGroup } -// NewState creates a new driver state. State changes take effect though -// the given output, derivation pipeline and network interfaces. -func NewState(driverCfg *Config, log log.Logger, snapshotLog log.Logger, config *rollup.Config, l1Chain L1Chain, l2Chain L2Chain, - output outputInterface, derivationPipeline DerivationPipeline, network Network, metrics Metrics) *state { - return &state{ - derivation: derivationPipeline, - idleDerivation: false, - syncStatusReq: make(chan chan eth.SyncStatus, 10), - forceReset: make(chan chan struct{}, 10), - Config: config, - DriverConfig: driverCfg, - done: make(chan struct{}), - log: log, - snapshotLog: snapshotLog, - l1: l1Chain, - l2: l2Chain, - output: output, - network: network, - metrics: metrics, - l1HeadSig: make(chan eth.L1BlockRef, 10), - l1SafeSig: make(chan eth.L1BlockRef, 10), - l1FinalizedSig: make(chan eth.L1BlockRef, 10), - unsafeL2Payloads: make(chan *eth.ExecutionPayload, 10), - } -} - // Start starts up the state loop. // The loop will have been started iff err is not nil. -func (s *state) Start(_ context.Context) error { +func (s *Driver) Start() error { s.derivation.Reset() s.wg.Add(1) @@ -108,7 +81,7 @@ func (s *state) Start(_ context.Context) error { return nil } -func (s *state) Close() error { +func (s *Driver) Close() error { s.done <- struct{}{} s.wg.Wait() return nil @@ -116,7 +89,7 @@ func (s *state) Close() error { // OnL1Head signals the driver that the L1 chain changed the "unsafe" block, // also known as head of the chain, or "latest". -func (s *state) OnL1Head(ctx context.Context, unsafe eth.L1BlockRef) error { +func (s *Driver) OnL1Head(ctx context.Context, unsafe eth.L1BlockRef) error { select { case <-ctx.Done(): return ctx.Err() @@ -127,7 +100,7 @@ func (s *state) OnL1Head(ctx context.Context, unsafe eth.L1BlockRef) error { // OnL1Safe signals the driver that the L1 chain changed the "safe", // also known as the justified checkpoint (as seen on L1 beacon-chain). -func (s *state) OnL1Safe(ctx context.Context, safe eth.L1BlockRef) error { +func (s *Driver) OnL1Safe(ctx context.Context, safe eth.L1BlockRef) error { select { case <-ctx.Done(): return ctx.Err() @@ -136,7 +109,7 @@ func (s *state) OnL1Safe(ctx context.Context, safe eth.L1BlockRef) error { } } -func (s *state) OnL1Finalized(ctx context.Context, finalized eth.L1BlockRef) error { +func (s *Driver) OnL1Finalized(ctx context.Context, finalized eth.L1BlockRef) error { select { case <-ctx.Done(): return ctx.Err() @@ -145,7 +118,7 @@ func (s *state) OnL1Finalized(ctx context.Context, finalized eth.L1BlockRef) err } } -func (s *state) OnUnsafeL2Payload(ctx context.Context, payload *eth.ExecutionPayload) error { +func (s *Driver) OnUnsafeL2Payload(ctx context.Context, payload *eth.ExecutionPayload) error { select { case <-ctx.Done(): return ctx.Err() @@ -154,94 +127,15 @@ func (s *state) OnUnsafeL2Payload(ctx context.Context, payload *eth.ExecutionPay } } -func (s *state) handleNewL1HeadBlock(head eth.L1BlockRef) { - // We don't need to do anything if the head hasn't changed. - if s.l1Head == (eth.L1BlockRef{}) { - s.log.Info("Received first L1 head signal", "l1_head", head) - } else if s.l1Head.Hash == head.Hash { - s.log.Trace("Received L1 head signal that is the same as the current head", "l1_head", head) - } else if s.l1Head.Hash == head.ParentHash { - // We got a new L1 block whose parent hash is the same as the current L1 head. Means we're - // dealing with a linear extension (new block is the immediate child of the old one). - s.log.Debug("L1 head moved forward", "l1_head", head) - } else { - if s.l1Head.Number >= head.Number { - s.metrics.RecordL1ReorgDepth(s.l1Head.Number - head.Number) - } - // New L1 block is not the same as the current head or a single step linear extension. - // This could either be a long L1 extension, or a reorg, or we simply missed a head update. - s.log.Warn("L1 head signal indicates a possible L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", head.ParentHash, "new_l1_head", head) - } - s.snapshot("New L1 Head") - s.metrics.RecordL1Ref("l1_head", head) - s.l1Head = head -} - -func (s *state) handleNewL1SafeBlock(safe eth.L1BlockRef) { - s.log.Info("New L1 safe block", "l1_safe", safe) - s.metrics.RecordL1Ref("l1_safe", safe) - s.l1Safe = safe -} - -func (s *state) handleNewL1FinalizedBlock(finalized eth.L1BlockRef) { - s.log.Info("New L1 finalized block", "l1_finalized", finalized) - s.metrics.RecordL1Ref("l1_finalized", finalized) - s.l1Finalized = finalized - s.derivation.Finalize(finalized.ID()) -} - -// findL1Origin determines what the next L1 Origin should be. -// The L1 Origin is either the L2 Head's Origin, or the following L1 block -// if the next L2 block's time is greater than or equal to the L2 Head's Origin. -func (s *state) findL1Origin(ctx context.Context) (eth.L1BlockRef, error) { - l2Head := s.derivation.UnsafeL2Head() - // If we are at the head block, don't do a lookup. - if l2Head.L1Origin.Hash == s.l1Head.Hash { - return s.l1Head, nil - } - - // Grab a reference to the current L1 origin block. - currentOrigin, err := s.l1.L1BlockRefByHash(ctx, l2Head.L1Origin.Hash) - if err != nil { - return eth.L1BlockRef{}, err - } - - if currentOrigin.Number+1+s.DriverConfig.SequencerConfDepth > s.l1Head.Number { - // TODO: we can decide to ignore confirmation depth if we would be forced - // to make an empty block (only deposits) by staying on the current origin. - s.log.Info("sequencing with old origin to preserve conf depth", - "current", currentOrigin, "current_time", currentOrigin.Time, - "l1_head", s.l1Head, "l1_head_time", s.l1Head.Time, - "l2_head", l2Head, "l2_head_time", l2Head.Time, - "depth", s.DriverConfig.SequencerConfDepth) - return currentOrigin, nil - } - - // Attempt to find the next L1 origin block, where the next origin is the immediate child of - // the current origin block. - nextOrigin, err := s.l1.L1BlockRefByNumber(ctx, currentOrigin.Number+1) - if err != nil { - s.log.Error("Failed to get next origin. Falling back to current origin", "err", err) - return currentOrigin, nil - } - - // If the next L2 block time is greater than the next origin block's time, we can choose to - // start building on top of the next origin. Sequencer implementation has some leeway here and - // could decide to continue to build on top of the previous origin until the Sequencer runs out - // of slack. For simplicity, we implement our Sequencer to always start building on the latest - // L1 block when we can. - if l2Head.Time+s.Config.BlockTime >= nextOrigin.Time { - return nextOrigin, nil - } - - return currentOrigin, nil -} - // createNewL2Block builds a L2 block on top of the L2 Head (unsafe). Used by Sequencer nodes to // construct new L2 blocks. Verifier nodes will use handleEpoch instead. -func (s *state) createNewL2Block(ctx context.Context) error { +func (s *Driver) createNewL2Block(ctx context.Context) error { + l2Head := s.derivation.UnsafeL2Head() + l2Safe := s.derivation.SafeL2Head() + l2Finalized := s.derivation.Finalized() + // Figure out which L1 origin block we're going to be building on top of. - l1Origin, err := s.findL1Origin(ctx) + l1Origin, err := s.l1OriginSelector.FindL1Origin(ctx, s.l1State.L1Head(), l2Head) if err != nil { s.log.Error("Error finding next L1 Origin", "err", err) return err @@ -249,17 +143,13 @@ func (s *state) createNewL2Block(ctx context.Context) error { // Rollup is configured to not start producing blocks until a specific L1 block has been // reached. Don't produce any blocks until we're at that genesis block. - if l1Origin.Number < s.Config.Genesis.L1.Number { - s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis", "next", l1Origin.ID(), "genesis", s.Config.Genesis.L1) + if l1Origin.Number < s.config.Genesis.L1.Number { + s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis", "next", l1Origin.ID(), "genesis", s.config.Genesis.L1) return nil } - l2Head := s.derivation.UnsafeL2Head() - l2Safe := s.derivation.SafeL2Head() - l2Finalized := s.derivation.Finalized() - // Should never happen. Sequencer will halt if we get into this situation somehow. - nextL2Time := l2Head.Time + s.Config.BlockTime + nextL2Time := l2Head.Time + s.config.BlockTime if nextL2Time < l1Origin.Time { s.log.Error("Cannot build L2 block for time before L1 origin", "l2Unsafe", l2Head, "nextL2Time", nextL2Time, "l1Origin", l1Origin, "l1OriginTime", l1Origin.Time) @@ -268,7 +158,7 @@ func (s *state) createNewL2Block(ctx context.Context) error { } // Actually create the new block. - newUnsafeL2Head, payload, err := s.output.createNewBlock(ctx, l2Head, l2Safe.ID(), l2Finalized.ID(), l1Origin) + newUnsafeL2Head, payload, err := s.sequencer.CreateNewBlock(ctx, l2Head, l2Safe.ID(), l2Finalized.ID(), l1Origin) if err != nil { s.log.Error("Could not extend chain as sequencer", "err", err, "l2_parent", l2Head, "l1_origin", l1Origin) return err @@ -292,7 +182,7 @@ func (s *state) createNewL2Block(ctx context.Context) error { } // the eventLoop responds to L1 changes and internal timers to produce L2 blocks. -func (s *state) eventLoop() { +func (s *Driver) eventLoop() { defer s.wg.Done() s.log.Info("State loop started") @@ -302,8 +192,8 @@ func (s *state) eventLoop() { // Start a ticker to produce L2 blocks at a constant rate. Ticker will only run if we're // running in Sequencer mode. var l2BlockCreationTickerCh <-chan time.Time - if s.DriverConfig.SequencerEnabled { - l2BlockCreationTicker := time.NewTicker(time.Duration(s.Config.BlockTime) * time.Second) + if s.driverConfig.SequencerEnabled { + l2BlockCreationTicker := time.NewTicker(time.Duration(s.config.BlockTime) * time.Second) defer l2BlockCreationTicker.Stop() l2BlockCreationTickerCh = l2BlockCreationTicker.C } @@ -371,8 +261,9 @@ func (s *state) eventLoop() { case <-l2BlockCreationReqCh: s.snapshot("L2 Block Creation Request") + l1Head := s.l1State.L1Head() if !s.idleDerivation { - s.log.Warn("not creating block, node is deriving new l2 data", "head_l1", s.l1Head) + s.log.Warn("not creating block, node is deriving new l2 data", "head_l1", l1Head) break } ctx, cancel := context.WithTimeout(ctx, 10*time.Second) @@ -388,8 +279,8 @@ func (s *state) eventLoop() { // requesting a new block ASAP instead of waiting for the next tick. // We don't request a block if the confirmation depth is not met. l2Head := s.derivation.UnsafeL2Head() - if s.l1Head.Number > l2Head.L1Origin.Number+s.DriverConfig.SequencerConfDepth { - s.log.Trace("Building another L2 block asap to catch up with L1 head", "l2_unsafe", l2Head, "l2_unsafe_l1_origin", l2Head.L1Origin, "l1_head", s.l1Head) + if l1Head.Number > l2Head.L1Origin.Number+s.driverConfig.SequencerConfDepth { + s.log.Trace("Building another L2 block asap to catch up with L1 head", "l2_unsafe", l2Head, "l2_unsafe_l1_origin", l2Head.L1Origin, "l1_head", l1Head) // But not too quickly to minimize busy-waiting for new blocks time.AfterFunc(time.Millisecond*10, reqL2BlockCreation) } @@ -402,13 +293,14 @@ func (s *state) eventLoop() { reqStep() case newL1Head := <-s.l1HeadSig: - s.handleNewL1HeadBlock(newL1Head) + s.l1State.HandleNewL1HeadBlock(newL1Head) reqStep() // a new L1 head may mean we have the data to not get an EOF again. case newL1Safe := <-s.l1SafeSig: - s.handleNewL1SafeBlock(newL1Safe) + s.l1State.HandleNewL1SafeBlock(newL1Safe) // no step, justified L1 information does not do anything for L2 derivation or status case newL1Finalized := <-s.l1FinalizedSig: - s.handleNewL1FinalizedBlock(newL1Finalized) + s.l1State.HandleNewL1FinalizedBlock(newL1Finalized) + s.derivation.Finalize(newL1Finalized.ID()) reqStep() // we may be able to mark more L2 data as finalized now case <-delayedStepReq: delayedStepReq = nil @@ -416,13 +308,13 @@ func (s *state) eventLoop() { case <-stepReqCh: s.metrics.SetDerivationIdle(false) s.idleDerivation = false - s.log.Debug("Derivation process step", "onto_origin", s.derivation.Progress().Origin, "onto_closed", s.derivation.Progress().Closed, "attempts", stepAttempts) + s.log.Debug("Derivation process step", "onto_origin", s.derivation.Origin(), "attempts", stepAttempts) stepCtx, cancel := context.WithTimeout(ctx, time.Second*10) // TODO pick a timeout for executing a single step err := s.derivation.Step(stepCtx) cancel() stepAttempts += 1 // count as attempt by default. We reset to 0 if we are making healthy progress. if err == io.EOF { - s.log.Debug("Derivation process went idle", "progress", s.derivation.Progress().Origin) + s.log.Debug("Derivation process went idle", "progress", s.derivation.Origin()) s.idleDerivation = true stepAttempts = 0 s.metrics.SetDerivationIdle(true) @@ -454,10 +346,10 @@ func (s *state) eventLoop() { } case respCh := <-s.syncStatusReq: respCh <- eth.SyncStatus{ - CurrentL1: s.derivation.Progress().Origin, - HeadL1: s.l1Head, - SafeL1: s.l1Safe, - FinalizedL1: s.l1Finalized, + CurrentL1: s.derivation.Origin(), + HeadL1: s.l1State.L1Head(), + SafeL1: s.l1State.L1Safe(), + FinalizedL1: s.l1State.L1Finalized(), UnsafeL2: s.derivation.UnsafeL2Head(), SafeL2: s.derivation.SafeL2Head(), FinalizedL2: s.derivation.Finalized(), @@ -476,8 +368,8 @@ func (s *state) eventLoop() { // ResetDerivationPipeline forces a reset of the derivation pipeline. // It waits for the reset to occur. It simply unblocks the caller rather // than fully cancelling the reset request upon a context cancellation. -func (s *state) ResetDerivationPipeline(ctx context.Context) error { - respCh := make(chan struct{}) +func (s *Driver) ResetDerivationPipeline(ctx context.Context) error { + respCh := make(chan struct{}, 1) select { case <-ctx.Done(): return ctx.Err() @@ -491,8 +383,8 @@ func (s *state) ResetDerivationPipeline(ctx context.Context) error { } } -func (s *state) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) { - respCh := make(chan eth.SyncStatus) +func (s *Driver) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) { + respCh := make(chan eth.SyncStatus, 1) select { case <-ctx.Done(): return nil, ctx.Err() @@ -516,11 +408,11 @@ func (v deferJSONString) String() string { return string(out) } -func (s *state) snapshot(event string) { +func (s *Driver) snapshot(event string) { s.snapshotLog.Info("Rollup State Snapshot", "event", event, - "l1Head", deferJSONString{s.l1Head}, - "l1Current", deferJSONString{s.derivation.Progress().Origin}, + "l1Head", deferJSONString{s.l1State.L1Head()}, + "l1Current", deferJSONString{s.derivation.Origin()}, "l2Head", deferJSONString{s.derivation.UnsafeL2Head()}, "l2Safe", deferJSONString{s.derivation.SafeL2Head()}, "l2FinalizedHead", deferJSONString{s.derivation.Finalized()}) diff --git a/op-node/rollup/driver/step.go b/op-node/rollup/driver/step.go deleted file mode 100644 index 983ad2218ce86..0000000000000 --- a/op-node/rollup/driver/step.go +++ /dev/null @@ -1,56 +0,0 @@ -package driver - -import ( - "context" - "fmt" - "time" - - "github.com/ethereum-optimism/optimism/op-node/eth" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum/go-ethereum/log" -) - -type outputImpl struct { - dl Downloader - l2 derive.Engine - log log.Logger - Config *rollup.Config -} - -func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *eth.ExecutionPayload, error) { - d.log.Info("creating new block", "parent", l2Head, "l1Origin", l1Origin) - - fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) - defer cancel() - - attrs, err := derive.PreparePayloadAttributes(fetchCtx, d.Config, d.dl, l2Head, l2Head.Time+d.Config.BlockTime, l1Origin.ID()) - if err != nil { - return l2Head, nil, err - } - - // If our next L2 block timestamp is beyond the Sequencer drift threshold, then we must produce - // empty blocks (other than the L1 info deposit and any user deposits). We handle this by - // setting NoTxPool to true, which will cause the Sequencer to not include any transactions - // from the transaction pool. - attrs.NoTxPool = uint64(attrs.Timestamp) >= l1Origin.Time+d.Config.MaxSequencerDrift - - // And construct our fork choice state. This is our current fork choice state and will be - // updated as a result of executing the block based on the attributes described above. - fc := eth.ForkchoiceState{ - HeadBlockHash: l2Head.Hash, - SafeBlockHash: l2SafeHead.Hash, - FinalizedBlockHash: l2Finalized.Hash, - } - - // Actually execute the block and add it to the head of the chain. - payload, errType, err := derive.InsertHeadBlock(ctx, d.log, d.l2, fc, attrs, false) - if err != nil { - return l2Head, nil, fmt.Errorf("failed to extend L2 chain, error (%d): %w", errType, err) - } - - // Generate an L2 block ref from the payload. - ref, err := derive.PayloadToBlockRef(payload, &d.Config.Genesis) - - return ref, payload, err -} diff --git a/op-node/sources/eth_client.go b/op-node/sources/eth_client.go index 2c5ae771d6b29..97f663383717e 100644 --- a/op-node/sources/eth_client.go +++ b/op-node/sources/eth_client.go @@ -2,8 +2,8 @@ package sources import ( "context" - "errors" "fmt" + "io" "github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/eth" @@ -81,7 +81,8 @@ type EthClient struct { log log.Logger // cache receipts in bundles per block hash - // common.Hash -> types.Receipts + // We cache the receipts fetcher to not lose progress when we have to retry the `Fetch` call + // common.Hash -> eth.ReceiptsFetcher receiptsCache *caching.LRUCache // cache transactions in bundles per block hash @@ -231,68 +232,42 @@ func (s *EthClient) PayloadByLabel(ctx context.Context, label eth.BlockLabel) (* return s.payloadCall(ctx, "eth_getBlockByNumber", string(label)) } -func (s *EthClient) Fetch(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, eth.ReceiptsFetcher, error) { +// FetchReceipts returns a block info and all of the receipts associated with transactions in the block. +// It verifies the receipt hash in the block header against the receipt hash of the fetched receipts +// to ensure that the execution engine did not fail to return any receipts. +func (s *EthClient) FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) { info, txs, err := s.InfoAndTxsByHash(ctx, blockHash) if err != nil { - return nil, nil, nil, err + return nil, nil, err } + // Try to reuse the receipts fetcher because is caches the results of intermediate calls. This means + // that if just one of many calls fail, we only retry the failed call rather than all of the calls. + // The underlying fetcher uses the receipts hash to verify receipt integrity. + var fetcher eth.ReceiptsFetcher if v, ok := s.receiptsCache.Get(blockHash); ok { - return info, txs, v.(eth.ReceiptsFetcher), nil - } - txHashes := make([]common.Hash, len(txs)) - for i := 0; i < len(txs); i++ { - txHashes[i] = txs[i].Hash() + fetcher = v.(eth.ReceiptsFetcher) + } else { + txHashes := make([]common.Hash, len(txs)) + for i := 0; i < len(txs); i++ { + txHashes[i] = txs[i].Hash() + } + fetcher = NewReceiptsFetcher(info.ID(), info.ReceiptHash(), txHashes, s.client.BatchCallContext, s.maxBatchSize) + s.receiptsCache.Add(blockHash, fetcher) } - r := NewReceiptsFetcher(info.ID(), info.ReceiptHash(), txHashes, s.client.BatchCallContext, s.maxBatchSize) - s.receiptsCache.Add(blockHash, r) - return info, txs, r, nil -} - -// BlockIDRange returns a range of block IDs from the provided begin up to max blocks after the begin. -// This batch-requests all blocks by number in the range at once, and then verifies the consistency -func (s *EthClient) BlockIDRange(ctx context.Context, begin eth.BlockID, max uint64) ([]eth.BlockID, error) { - headerRequests := make([]rpc.BatchElem, max) - for i := uint64(0); i < max; i++ { - headerRequests[i] = rpc.BatchElem{ - Method: "eth_getBlockByNumber", - Args: []interface{}{hexutil.EncodeUint64(begin.Number + 1 + i), false}, - Result: new(*rpcHeader), - Error: nil, + // Fetch all receipts + for { + if err := fetcher.Fetch(ctx); err == io.EOF { + break + } else if err != nil { + return nil, nil, err } } - if err := s.client.BatchCallContext(ctx, headerRequests); err != nil { - return nil, err + receipts, err := fetcher.Result() + if err != nil { + return nil, nil, err } - out := make([]eth.BlockID, 0, max) - - // try to cache everything we have before halting on the results with errors - for i := 0; i < len(headerRequests); i++ { - result := *headerRequests[i].Result.(**rpcHeader) - if headerRequests[i].Error == nil { - if result == nil { - break // no more headers from here - } - info, err := result.Info(s.trustRPC, s.mustBePostMerge) - if err != nil { - return nil, fmt.Errorf("bad header data for block %s: %w", headerRequests[i].Args[0], err) - } - s.headersCache.Add(info.Hash(), info) - out = append(out, info.ID()) - prev := begin - if i > 0 { - prev = out[i-1] - } - if prev.Hash != info.ParentHash() { - return nil, fmt.Errorf("inconsistent results from L1 chain range request, block %s not expected parent %s of %s", prev, info.ParentHash(), info.ID()) - } - } else if errors.Is(headerRequests[i].Error, ethereum.NotFound) { - break // no more headers from here - } else { - return nil, fmt.Errorf("failed to retrieve block: %s: %w", headerRequests[i].Args[0], headerRequests[i].Error) - } - } - return out, nil + return info, receipts, nil } func (s *EthClient) GetProof(ctx context.Context, address common.Address, blockTag string) (*eth.AccountResult, error) { diff --git a/op-node/sources/eth_client_test.go b/op-node/sources/eth_client_test.go index 16535f3888584..bca40e087a73b 100644 --- a/op-node/sources/eth_client_test.go +++ b/op-node/sources/eth_client_test.go @@ -6,6 +6,7 @@ import ( "math/rand" "testing" + "github.com/ethereum/go-ethereum" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -30,7 +31,7 @@ func (m *mockRPC) CallContext(ctx context.Context, result interface{}, method st return m.MethodCalled("CallContext", ctx, result, method, args).Get(0).([]error)[0] } -func (m *mockRPC) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) { +func (m *mockRPC) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) { called := m.MethodCalled("EthSubscribe", channel, args) return called.Get(0).(*rpc.ClientSubscription), called.Get(1).([]error)[0] } diff --git a/op-node/sources/limit.go b/op-node/sources/limit.go index 9de8933ffe596..d722631e31b43 100644 --- a/op-node/sources/limit.go +++ b/op-node/sources/limit.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/ethereum-optimism/optimism/op-node/client" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/rpc" ) @@ -39,7 +40,7 @@ func (lc *limitClient) CallContext(ctx context.Context, result interface{}, meth return lc.c.CallContext(ctx, result, method, args...) } -func (lc *limitClient) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) { +func (lc *limitClient) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) { // subscription doesn't count towards request limit return lc.c.EthSubscribe(ctx, channel, args...) } diff --git a/op-node/sources/rollupclient.go b/op-node/sources/rollupclient.go index 1c10583ca2e88..577c69dcadc61 100644 --- a/op-node/sources/rollupclient.go +++ b/op-node/sources/rollupclient.go @@ -4,17 +4,17 @@ import ( "context" "math/big" + "github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/rpc" ) type RollupClient struct { - rpc *rpc.Client + rpc client.RPC } -func NewRollupClient(rpc *rpc.Client) *RollupClient { +func NewRollupClient(rpc client.RPC) *RollupClient { return &RollupClient{rpc} } diff --git a/op-node/testlog/testlog.go b/op-node/testlog/testlog.go index 1eb70a52a2540..bc145e3eeb9ae 100644 --- a/op-node/testlog/testlog.go +++ b/op-node/testlog/testlog.go @@ -22,18 +22,24 @@ import ( "strconv" "strings" "sync" - "testing" "github.com/ethereum/go-ethereum/log" ) +// Testing interface to log to. Some functions are marked as Helper function to log the call site accurately. +// Standard Go testing.TB implements this, as well as Hive and other Go-like test frameworks. +type Testing interface { + Logf(format string, args ...any) + Helper() +} + // Handler returns a log handler which logs to the unit test log of t. -func Handler(t *testing.T, level log.Lvl) log.Handler { +func Handler(t Testing, level log.Lvl) log.Handler { return log.LvlFilterHandler(level, &handler{t, log.TerminalFormat(false)}) } type handler struct { - t *testing.T + t Testing fmt log.Format } @@ -47,7 +53,7 @@ func (h *handler) Log(r *log.Record) error { // helpers, so the file and line number in unit test output correspond to the call site // which emitted the log message. type logger struct { - t *testing.T + t Testing l log.Logger mu *sync.Mutex h *bufHandler @@ -64,7 +70,7 @@ func (h *bufHandler) Log(r *log.Record) error { } // Logger returns a logger which logs to the unit test log of t. -func Logger(t *testing.T, level log.Lvl) log.Logger { +func Logger(t Testing, level log.Lvl) log.Logger { l := &logger{ t: t, l: log.New(), diff --git a/op-node/testutils/assertions.go b/op-node/testutils/assertions.go new file mode 100644 index 0000000000000..47d44e7dbd997 --- /dev/null +++ b/op-node/testutils/assertions.go @@ -0,0 +1,20 @@ +package testutils + +import ( + "math/big" + "testing" +) + +func BigEqual(a, b *big.Int) bool { + if a == nil || b == nil { + return a == b + } else { + return a.Cmp(b) == 0 + } +} + +func RequireBigEqual(t *testing.T, exp, actual *big.Int) { + if !BigEqual(exp, actual) { + t.Fatalf("expected %s to be equal to %s", exp.String(), actual.String()) + } +} diff --git a/op-node/testutils/metrics.go b/op-node/testutils/metrics.go new file mode 100644 index 0000000000000..36c8001e2fe07 --- /dev/null +++ b/op-node/testutils/metrics.go @@ -0,0 +1,42 @@ +package testutils + +import "github.com/ethereum-optimism/optimism/op-node/eth" + +// TestDerivationMetrics implements the metrics used in the derivation pipeline as no-op operations. +// Optionally a test may hook into the metrics +type TestDerivationMetrics struct { + FnRecordL1ReorgDepth func(d uint64) + FnRecordL1Ref func(name string, ref eth.L1BlockRef) + FnRecordL2Ref func(name string, ref eth.L2BlockRef) + FnRecordUnsafePayloads func(length uint64, memSize uint64, next eth.BlockID) +} + +func (t *TestDerivationMetrics) RecordL1ReorgDepth(d uint64) { + if t.FnRecordL1ReorgDepth != nil { + t.FnRecordL1ReorgDepth(d) + } +} + +func (t *TestDerivationMetrics) RecordL1Ref(name string, ref eth.L1BlockRef) { + if t.FnRecordL1Ref != nil { + t.FnRecordL1Ref(name, ref) + } +} + +func (t *TestDerivationMetrics) RecordL2Ref(name string, ref eth.L2BlockRef) { + if t.FnRecordL2Ref != nil { + t.FnRecordL2Ref(name, ref) + } +} + +func (t *TestDerivationMetrics) RecordUnsafePayloadsBuffer(length uint64, memSize uint64, next eth.BlockID) { + if t.FnRecordUnsafePayloads != nil { + t.FnRecordUnsafePayloads(length, memSize, next) + } +} + +type TestRPCMetrics struct{} + +func (n *TestRPCMetrics) RecordRPCServerRequest(method string) func() { + return func() {} +} diff --git a/op-node/testutils/mock_eth_client.go b/op-node/testutils/mock_eth_client.go index 31dfe04bc1a87..2c377c4871336 100644 --- a/op-node/testutils/mock_eth_client.go +++ b/op-node/testutils/mock_eth_client.go @@ -105,13 +105,13 @@ func (m *MockEthClient) ExpectPayloadByLabel(label eth.BlockLabel, payload *eth. m.Mock.On("PayloadByLabel", label).Once().Return(payload, &err) } -func (m *MockEthClient) Fetch(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, eth.ReceiptsFetcher, error) { - out := m.Mock.MethodCalled("Fetch", blockHash) - return *out[0].(*eth.BlockInfo), out[1].(types.Transactions), out[2].(eth.ReceiptsFetcher), *out[3].(*error) +func (m *MockEthClient) FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) { + out := m.Mock.MethodCalled("FetchReceipts", blockHash) + return *out[0].(*eth.BlockInfo), out[1].(types.Receipts), *out[2].(*error) } -func (m *MockEthClient) ExpectFetch(hash common.Hash, info eth.BlockInfo, transactions types.Transactions, receipts types.Receipts, err error) { - m.Mock.On("Fetch", hash).Once().Return(&info, transactions, eth.FetchedReceipts(receipts), &err) +func (m *MockEthClient) ExpectFetchReceipts(hash common.Hash, info eth.BlockInfo, receipts types.Receipts, err error) { + m.Mock.On("FetchReceipts", hash).Once().Return(&info, receipts, &err) } func (m *MockEthClient) GetProof(ctx context.Context, address common.Address, blockTag string) (*eth.AccountResult, error) { diff --git a/op-node/testutils/rpc_err_faker.go b/op-node/testutils/rpc_err_faker.go new file mode 100644 index 0000000000000..8aa5735a47255 --- /dev/null +++ b/op-node/testutils/rpc_err_faker.go @@ -0,0 +1,52 @@ +package testutils + +import ( + "context" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/rpc" + + "github.com/ethereum-optimism/optimism/op-node/client" +) + +// RPCErrFaker implements an RPC by wrapping one, but returns an error when prepared with one, to test RPC error handling. +type RPCErrFaker struct { + // RPC to call when no ErrFn is set, or the ErrFn does not return an error + RPC client.RPC + // ErrFn returns an error when the RPC needs to return error upon a call, batch call or subscription. + // The RPC operates without fake errors if the ErrFn is nil, or returns nil. + ErrFn func() error +} + +func (r RPCErrFaker) Close() { + r.RPC.Close() +} + +func (r RPCErrFaker) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + if r.ErrFn != nil { + if err := r.ErrFn(); err != nil { + return err + } + } + return r.RPC.CallContext(ctx, result, method, args...) +} + +func (r RPCErrFaker) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + if r.ErrFn != nil { + if err := r.ErrFn(); err != nil { + return err + } + } + return r.RPC.BatchCallContext(ctx, b) +} + +func (r RPCErrFaker) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) { + if r.ErrFn != nil { + if err := r.ErrFn(); err != nil { + return nil, err + } + } + return r.RPC.EthSubscribe(ctx, channel, args...) +} + +var _ client.RPC = (*RPCErrFaker)(nil) diff --git a/op-node/withdrawals/testdata/bridge-withdrawal.json b/op-node/withdrawals/testdata/bridge-withdrawal.json new file mode 100644 index 0000000000000..ad9851b8001a2 --- /dev/null +++ b/op-node/withdrawals/testdata/bridge-withdrawal.json @@ -0,0 +1,134 @@ +{ + "type": "0x2", + "root": "0x", + "status": "0x1", + "cumulativeGasUsed": "0x28786", + "logsBloom": "0x0000000000004000001000000000000000000000000000100010000000100000000000000000808000000000020400800000000000000004000010000000000000002000000004004000000800000010040000000000000000000000000000000000000012000000000000000000080088080000000200000000001c000000000200000000000000000040000100000000800000000000000001000000201000000000000002004201008000000001000000200000400000000000000000100000000052000200000100000408020010000002100000000000040000200020000000000000000200000100400000000000000000000000000001100000000000", + "logs": [ + { + "address": "0x7c6b91d9be155a6db01f749217d76ff02a7227f2", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a2", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000001f4", + "blockNumber": "0x36", + "transactionHash": "0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add", + "transactionIndex": "0x1", + "blockHash": "0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df", + "logIndex": "0x0", + "removed": false + }, + { + "address": "0x7c6b91d9be155a6db01f749217d76ff02a7227f2", + "topics": [ + "0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5", + "0x000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a2" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000001f4", + "blockNumber": "0x36", + "transactionHash": "0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add", + "transactionIndex": "0x1", + "blockHash": "0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df", + "logIndex": "0x1", + "removed": false + }, + { + "address": "0x4200000000000000000000000000000000000016", + "topics": [ + "0x7744840cae4793a72467311120512aa98e4398bcd2b9d379b2b9c3b60fa03d72", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004200000000000000000000000000000000000007", + "0x0000000000000000000000006900000000000000000000000000000000000002" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031b80000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e4d764ad0b0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000001000000000000000000000000069000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e40166a07a00000000000000000000000089d51be807d98fc974a0f41b2e67a8228d7846ef0000000000000000000000007c6b91d9be155a6db01f749217d76ff02a7227f2000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a2000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x36", + "transactionHash": "0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add", + "transactionIndex": "0x1", + "blockHash": "0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df", + "logIndex": "0x2", + "removed": false + }, + { + "address": "0x4200000000000000000000000000000000000016", + "topics": [ + "0xedd348f9c36ef1a5b0747bb5039752707059f0b934c8e508b3271e08fbd0122c", + "0x0d827f8148288e3a2466018f71b968ece4ea9f9e2a81c30da9bd46cce2868285" + ], + "data": "0x", + "blockNumber": "0x36", + "transactionHash": "0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add", + "transactionIndex": "0x1", + "blockHash": "0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df", + "logIndex": "0x3", + "removed": false + }, + { + "address": "0x4200000000000000000000000000000000000007", + "topics": [ + "0xcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a", + "0x0000000000000000000000006900000000000000000000000000000000000003" + ], + "data": "0x000000000000000000000000420000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000800001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e40166a07a00000000000000000000000089d51be807d98fc974a0f41b2e67a8228d7846ef0000000000000000000000007c6b91d9be155a6db01f749217d76ff02a7227f2000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a2000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x36", + "transactionHash": "0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add", + "transactionIndex": "0x1", + "blockHash": "0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df", + "logIndex": "0x4", + "removed": false + }, + { + "address": "0x4200000000000000000000000000000000000007", + "topics": [ + "0x8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d546", + "0x0000000000000000000000004200000000000000000000000000000000000010" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x36", + "transactionHash": "0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add", + "transactionIndex": "0x1", + "blockHash": "0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df", + "logIndex": "0x5", + "removed": false + }, + { + "address": "0x4200000000000000000000000000000000000010", + "topics": [ + "0x7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf", + "0x0000000000000000000000007c6b91d9be155a6db01f749217d76ff02a7227f2", + "0x00000000000000000000000089d51be807d98fc974a0f41b2e67a8228d7846ef", + "0x000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a2" + ], + "data": "0x000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x36", + "transactionHash": "0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add", + "transactionIndex": "0x1", + "blockHash": "0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df", + "logIndex": "0x6", + "removed": false + }, + { + "address": "0x4200000000000000000000000000000000000010", + "topics": [ + "0x73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e", + "0x00000000000000000000000089d51be807d98fc974a0f41b2e67a8228d7846ef", + "0x0000000000000000000000007c6b91d9be155a6db01f749217d76ff02a7227f2", + "0x000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a2" + ], + "data": "0x000000000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x36", + "transactionHash": "0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add", + "transactionIndex": "0x1", + "blockHash": "0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df", + "logIndex": "0x7", + "removed": false + } + ], + "transactionHash": "0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x28786", + "blockHash": "0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df", + "blockNumber": "0x36", + "transactionIndex": "0x1" +} diff --git a/op-node/withdrawals/utils.go b/op-node/withdrawals/utils.go index 6b5ec3f1a9a04..5b4217f20e4de 100644 --- a/op-node/withdrawals/utils.go +++ b/op-node/withdrawals/utils.go @@ -21,6 +21,9 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +var MessagePassedTopic = crypto.Keccak256Hash([]byte("MessagePassed(uint256,address,address,uint256,uint256,bytes)")) +var MessagePassedExtension1Topic = crypto.Keccak256Hash([]byte("MessagePassedExtension1(bytes32)")) + // WaitForFinalizationPeriod waits until there is OutputProof for an L2 block number larger than the supplied l2BlockNumber // and that the output is finalized. // This functions polls and can block for a very long time if used on mainnet. @@ -169,11 +172,11 @@ func FinalizeWithdrawalParameters(ctx context.Context, l2client ProofClient, txH return FinalizedWithdrawalParameters{}, err } // Parse the receipt - ev, err := ParseWithdrawalInitiated(receipt) + ev, err := ParseMessagePassed(receipt) if err != nil { return FinalizedWithdrawalParameters{}, err } - ev1, err := ParseWithdrawalInitiatedExtension1(receipt) + ev1, err := ParseMessagePassedExtension1(receipt) if err != nil { return FinalizedWithdrawalParameters{}, err } @@ -241,7 +244,7 @@ var ( // - I don't like having to use the ABI Generated struct // - There should be a better way to run the ABI encoding // - These needs to be fuzzed against the solidity -func WithdrawalHash(ev *bindings.L2ToL1MessagePasserWithdrawalInitiated) (common.Hash, error) { +func WithdrawalHash(ev *bindings.L2ToL1MessagePasserMessagePassed) (common.Hash, error) { // abi.encode(nonce, msg.sender, _target, msg.value, _gasLimit, _data) args := abi.Arguments{ {Name: "nonce", Type: Uint256Type}, @@ -258,58 +261,50 @@ func WithdrawalHash(ev *bindings.L2ToL1MessagePasserWithdrawalInitiated) (common return crypto.Keccak256Hash(enc), nil } -// ParseWithdrawalInitiated parses -func ParseWithdrawalInitiated(receipt *types.Receipt) (*bindings.L2ToL1MessagePasserWithdrawalInitiated, error) { +// ParseMessagePassed parses MessagePassed events from +// a transaction receipt. It does not support multiple withdrawals +// per receipt. +func ParseMessagePassed(receipt *types.Receipt) (*bindings.L2ToL1MessagePasserMessagePassed, error) { contract, err := bindings.NewL2ToL1MessagePasser(common.Address{}, nil) if err != nil { return nil, err } - abi, err := bindings.L2ToL1MessagePasserMetaData.GetAbi() - if err != nil { - return nil, err - } for _, log := range receipt.Logs { - event, err := abi.EventByID(log.Topics[0]) - if err != nil { - return nil, err + if len(log.Topics) == 0 || log.Topics[0] != MessagePassedTopic { + continue } - if event.Name == "WithdrawalInitiated" { - ev, err := contract.ParseWithdrawalInitiated(*log) - if err != nil { - return nil, fmt.Errorf("failed to parse log: %w", err) - } - return ev, nil + + ev, err := contract.ParseMessagePassed(*log) + if err != nil { + return nil, fmt.Errorf("failed to parse log: %w", err) } + return ev, nil } - return nil, errors.New("Unable to find WithdrawalInitiated event") + return nil, errors.New("Unable to find MessagePassed event") } -// ParseWithdrawalInitiatedExtension1 parses -func ParseWithdrawalInitiatedExtension1(receipt *types.Receipt) (*bindings.L2ToL1MessagePasserWithdrawalInitiatedExtension1, error) { +// ParseMessagePassedExtension1 parses MessagePassedExtension1 events +// from a transaction receipt. It does not support multiple withdrawals per +// receipt. +func ParseMessagePassedExtension1(receipt *types.Receipt) (*bindings.L2ToL1MessagePasserMessagePassedExtension1, error) { contract, err := bindings.NewL2ToL1MessagePasser(common.Address{}, nil) if err != nil { return nil, err } - abi, err := bindings.L2ToL1MessagePasserMetaData.GetAbi() - if err != nil { - return nil, err - } for _, log := range receipt.Logs { - event, err := abi.EventByID(log.Topics[0]) - if err != nil { - return nil, err + if len(log.Topics) == 0 || log.Topics[0] != MessagePassedExtension1Topic { + continue } - if event.Name == "WithdrawalInitiatedExtension1" { - ev, err := contract.ParseWithdrawalInitiatedExtension1(*log) - if err != nil { - return nil, fmt.Errorf("failed to parse log: %w", err) - } - return ev, nil + + ev, err := contract.ParseMessagePassedExtension1(*log) + if err != nil { + return nil, fmt.Errorf("failed to parse log: %w", err) } + return ev, nil } - return nil, errors.New("Unable to find WithdrawalInitiatedExtension1 event") + return nil, errors.New("Unable to find MessagePassedExtension1 event") } // StorageSlotOfWithdrawalHash determines the storage slot of the Withdrawer contract to look at diff --git a/op-node/withdrawals/utils_test.go b/op-node/withdrawals/utils_test.go new file mode 100644 index 0000000000000..eb3ab6e0a8bbe --- /dev/null +++ b/op-node/withdrawals/utils_test.go @@ -0,0 +1,160 @@ +package withdrawals + +import ( + "encoding/json" + "math/big" + "os" + "path" + "testing" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-node/testutils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +func TestParseMessagePassed(t *testing.T) { + tests := []struct { + name string + file string + expected *bindings.L2ToL1MessagePasserMessagePassed + }{ + { + "withdrawal through bridge", + "bridge-withdrawal.json", + &bindings.L2ToL1MessagePasserMessagePassed{ + Nonce: new(big.Int), + Sender: common.HexToAddress("0x4200000000000000000000000000000000000007"), + Target: common.HexToAddress("0x6900000000000000000000000000000000000002"), + Value: new(big.Int), + GasLimit: big.NewInt(203648), + Data: hexutil.MustDecode( + "0xd764ad0b00010000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000042000000000000000000000000000000" + + "0000001000000000000000000000000069000000000000000000000000000000" + + "0000000300000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "000000c000000000000000000000000000000000000000000000000000000000" + + "000000e40166a07a00000000000000000000000089d51be807d98fc974a0f41b" + + "2e67a8228d7846ef0000000000000000000000007c6b91d9be155a6db01f7492" + + "17d76ff02a7227f2000000000000000000000000c20c5ec92fda6e611a084851" + + "23cdc0d5b84bd3a2000000000000000000000000c20c5ec92fda6e611a084851" + + "23cdc0d5b84bd3a2000000000000000000000000000000000000000000000000" + + "00000000000001f4000000000000000000000000000000000000000000000000" + + "00000000000000c0000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "00000000", + ), + Raw: types.Log{ + Address: common.HexToAddress("0x4200000000000000000000000000000000000016"), + Topics: []common.Hash{ + common.HexToHash("0x7744840cae4793a72467311120512aa98e4398bcd2b9d379b2b9c3b60fa03d72"), + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), + common.HexToHash("0x0000000000000000000000004200000000000000000000000000000000000007"), + common.HexToHash("0x0000000000000000000000006900000000000000000000000000000000000002"), + }, + Data: hexutil.MustDecode( + "0x00000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000031b80" + + "000000000000000000000000000000000000000000000000000000000000006000" + + "000000000000000000000000000000000000000000000000000000000001e4d764" + + "ad0b00010000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000004200000000000000000000000000000000000010" + + "000000000000000000000000690000000000000000000000000000000000000300" + + "000000000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000c000000000" + + "000000000000000000000000000000000000000000000000000000e40166a07a00" + + "000000000000000000000089d51be807d98fc974a0f41b2e67a8228d7846ef0000" + + "000000000000000000007c6b91d9be155a6db01f749217d76ff02a7227f2000000" + + "000000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a200000000" + + "0000000000000000c20c5ec92fda6e611a08485123cdc0d5b84bd3a20000000000" + + "0000000000000000000000000000000000000000000000000001f4000000000000" + + "00000000000000000000000000000000000000000000000000c000000000000000" + + "000000000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000", + ), + BlockNumber: 0x36, + TxHash: common.HexToHash("0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add"), + TxIndex: 1, + BlockHash: common.HexToHash("0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df"), + Index: 2, + Removed: false, + }, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + f, err := os.Open(path.Join("testdata", test.file)) + require.NoError(t, err) + dec := json.NewDecoder(f) + receipt := new(types.Receipt) + require.NoError(t, dec.Decode(receipt)) + parsed, err := ParseMessagePassed(receipt) + require.NoError(t, err) + + // Have to do this weird thing to compare zero bigints. + // When they're deserialized from JSON, the internal byte + // array is an empty array whereas it is nil in the expectation. + parsedNonce := parsed.Nonce + parsedValue := parsed.Value + expNonce := test.expected.Nonce + expValue := test.expected.Value + testutils.RequireBigEqual(t, expNonce, parsedNonce) + testutils.RequireBigEqual(t, expValue, parsedValue) + parsed.Nonce = nil + parsed.Value = nil + test.expected.Nonce = nil + test.expected.Value = nil + + require.EqualValues(t, test.expected, parsed) + }) + } +} + +func TestParseMessagePassedExtension1(t *testing.T) { + tests := []struct { + name string + file string + expected *bindings.L2ToL1MessagePasserMessagePassedExtension1 + }{ + { + "withdrawal through bridge", + "bridge-withdrawal.json", + &bindings.L2ToL1MessagePasserMessagePassedExtension1{ + Hash: common.HexToHash("0x0d827f8148288e3a2466018f71b968ece4ea9f9e2a81c30da9bd46cce2868285"), + Raw: types.Log{ + Address: common.HexToAddress("0x4200000000000000000000000000000000000016"), + Topics: []common.Hash{ + common.HexToHash("0xedd348f9c36ef1a5b0747bb5039752707059f0b934c8e508b3271e08fbd0122c"), + common.HexToHash("0x0d827f8148288e3a2466018f71b968ece4ea9f9e2a81c30da9bd46cce2868285"), + }, + Data: []byte{}, + BlockNumber: 0x36, + TxHash: common.HexToHash("0x9346381068b59d2098495baa72ed2f773c1e09458610a7a208984859dff73add"), + TxIndex: 0x1, + BlockHash: common.HexToHash("0xfdd4ad8a984b45687aca0463db491cbd0e85273d970019a3f8bf618b614938df"), + Index: 0x3, + Removed: false, + }, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + f, err := os.Open(path.Join("testdata", test.file)) + require.NoError(t, err) + dec := json.NewDecoder(f) + receipt := new(types.Receipt) + require.NoError(t, dec.Decode(receipt)) + parsed, err := ParseMessagePassedExtension1(receipt) + require.NoError(t, err) + require.EqualValues(t, test.expected, parsed) + }) + } +} diff --git a/op-proposer/go.mod b/op-proposer/go.mod index 23bbd4aebcb80..c4a73a667e98d 100644 --- a/op-proposer/go.mod +++ b/op-proposer/go.mod @@ -3,9 +3,9 @@ module github.com/ethereum-optimism/optimism/op-proposer go 1.18 require ( - github.com/ethereum-optimism/optimism/op-bindings v0.8.8 - github.com/ethereum-optimism/optimism/op-node v0.8.8 - github.com/ethereum-optimism/optimism/op-service v0.8.8 + github.com/ethereum-optimism/optimism/op-bindings v0.8.10 + github.com/ethereum-optimism/optimism/op-node v0.8.10 + github.com/ethereum-optimism/optimism/op-service v0.8.10 github.com/ethereum/go-ethereum v1.10.23 github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/stretchr/testify v1.8.0 diff --git a/op-proposer/go.sum b/op-proposer/go.sum index 570625bcf261c..69e2e3a769da7 100644 --- a/op-proposer/go.sum +++ b/op-proposer/go.sum @@ -150,12 +150,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd h1:NchOnosWOkH9wlix8QevGHE+6vuRa+OMGvDNsczv2kQ= github.com/ethereum-optimism/op-geth v0.0.0-20220926184707-53d23c240afd/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8 h1:HN625JI2VsRsli+U6GAXipg7lAKx8EOmGIovN79Az+I= -github.com/ethereum-optimism/optimism/op-bindings v0.8.8/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= -github.com/ethereum-optimism/optimism/op-node v0.8.8 h1:WuZF1RsZnB+u/wwWToVaC1lZWfGfgncLusUssA3Hm+o= -github.com/ethereum-optimism/optimism/op-node v0.8.8/go.mod h1:O5nXPCx8vn9c/CHgBC7vP5utcanIQ4uhWKkJ3pAaaSQ= -github.com/ethereum-optimism/optimism/op-service v0.8.8 h1:k5E78Zr2cGU0SwjoHpFXuC1eyfXhu3oKEOnDDaFi57I= -github.com/ethereum-optimism/optimism/op-service v0.8.8/go.mod h1:K0uybOhICTc2yfhrRj0cD1m7aPkOf5C9e6bUmvf4rGA= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10 h1:aSAWCQwBQnbmv03Gvtuvn3qfTWrZu/sTlRAWrpQhiHc= +github.com/ethereum-optimism/optimism/op-bindings v0.8.10/go.mod h1:pyTCbh2o/SY+5/AL2Qo5GgAao3Gtt9Ff6tfK9Pa9emM= +github.com/ethereum-optimism/optimism/op-node v0.8.10 h1:1Gc4FtR5B+HgfQ+byNn3P+tiJarpMZSYjj5iLvA3YtU= +github.com/ethereum-optimism/optimism/op-node v0.8.10/go.mod h1:6NkgIThuQbPY6fA9lI2A52DaeLM2FvrcwGCBVEY2fS8= +github.com/ethereum-optimism/optimism/op-service v0.8.10 h1:K3IABHI1b0MDrDXALvTKTbzy6IogGD6NgmbqfKEcEwM= +github.com/ethereum-optimism/optimism/op-service v0.8.10/go.mod h1:K0uybOhICTc2yfhrRj0cD1m7aPkOf5C9e6bUmvf4rGA= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= diff --git a/op-proposer/l2_output_submitter.go b/op-proposer/l2_output_submitter.go index 064d08ba21ea8..a5655a3a1b007 100644 --- a/op-proposer/l2_output_submitter.go +++ b/op-proposer/l2_output_submitter.go @@ -12,9 +12,7 @@ import ( "syscall" "time" - hdwallet "github.com/miguelmota/go-ethereum-hdwallet" - "github.com/urfave/cli" - + "github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/sources" "github.com/ethereum-optimism/optimism/op-proposer/drivers/l2output" "github.com/ethereum-optimism/optimism/op-proposer/txmgr" @@ -28,6 +26,8 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" + hdwallet "github.com/miguelmota/go-ethereum-hdwallet" + "github.com/urfave/cli" ) const ( @@ -86,6 +86,8 @@ func Main(version string) func(ctx *cli.Context) error { l.Error("error starting metrics server", err) } }() + addr := l2OutputSubmitter.l2OutputService.cfg.Driver.WalletAddr() + opmetrics.LaunchBalanceMetrics(ctx, l, registry, "", l2OutputSubmitter.l2OutputService.cfg.L1Client, addr) } rpcCfg := cfg.RPCConfig @@ -250,12 +252,12 @@ func dialRollupClientWithTimeout(ctx context.Context, url string) (*sources.Roll ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout) defer cancel() - client, err := rpc.DialContext(ctxt, url) + rpcCl, err := rpc.DialContext(ctxt, url) if err != nil { return nil, err } - return sources.NewRollupClient(client), nil + return sources.NewRollupClient(client.NewBaseRPCClient(rpcCl)), nil } // parseAddress parses an ETH address from a hex string. This method will fail if diff --git a/op-proposer/rollupclient/rollupclient.go b/op-proposer/rollupclient/rollupclient.go deleted file mode 100644 index d6bd8a37389f1..0000000000000 --- a/op-proposer/rollupclient/rollupclient.go +++ /dev/null @@ -1,14 +0,0 @@ -package rollupclient - -import ( - "github.com/ethereum-optimism/optimism/op-node/sources" - "github.com/ethereum/go-ethereum/rpc" -) - -// Deprecated: use sources.RollupClient instead -type RollupClient = sources.RollupClient - -// Deprecated: use sources.NewRollupClient instead -func NewRollupClient(rpc *rpc.Client) *sources.RollupClient { - return sources.NewRollupClient(rpc) -} diff --git a/op-node/backoff/operation.go b/op-service/backoff/operation.go similarity index 55% rename from op-node/backoff/operation.go rename to op-service/backoff/operation.go index 548188754f576..cecd67cca3957 100644 --- a/op-node/backoff/operation.go +++ b/op-service/backoff/operation.go @@ -1,6 +1,7 @@ package backoff import ( + "context" "fmt" "time" ) @@ -24,21 +25,37 @@ func (e *ErrFailedPermanently) Error() string { // with delays in between each retry according to the provided // Strategy. func Do(maxAttempts int, strategy Strategy, op Operation) error { + return DoCtx(context.Background(), maxAttempts, strategy, op) +} + +func DoCtx(ctx context.Context, maxAttempts int, strategy Strategy, op Operation) error { var attempt int + reattemptCh := make(chan struct{}, 1) + doReattempt := func() { + reattemptCh <- struct{}{} + } + doReattempt() + for { - attempt++ - err := op() - if err == nil { - return nil - } + select { + case <-ctx.Done(): + return ctx.Err() + case <-reattemptCh: + attempt++ + err := op() + if err == nil { + return nil + } - if attempt == maxAttempts { - return &ErrFailedPermanently{ - attempts: maxAttempts, - LastErr: err, + if attempt == maxAttempts { + return &ErrFailedPermanently{ + attempts: maxAttempts, + LastErr: err, + } } + time.AfterFunc(strategy.Duration(attempt-1), doReattempt) } - time.Sleep(strategy.Duration(attempt - 1)) + } } diff --git a/op-node/backoff/operation_test.go b/op-service/backoff/operation_test.go similarity index 100% rename from op-node/backoff/operation_test.go rename to op-service/backoff/operation_test.go diff --git a/op-node/backoff/strategies.go b/op-service/backoff/strategies.go similarity index 100% rename from op-node/backoff/strategies.go rename to op-service/backoff/strategies.go diff --git a/op-node/backoff/strategies_test.go b/op-service/backoff/strategies_test.go similarity index 100% rename from op-node/backoff/strategies_test.go rename to op-service/backoff/strategies_test.go diff --git a/op-service/go.sum b/op-service/go.sum index 24130690f718a..0870d7e345066 100644 --- a/op-service/go.sum +++ b/op-service/go.sum @@ -102,6 +102,7 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -119,6 +120,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -205,6 +207,7 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -241,6 +244,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= @@ -406,6 +411,7 @@ github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSg github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 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= @@ -432,6 +438,7 @@ github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -454,6 +461,7 @@ github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYa github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= @@ -661,6 +669,7 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/op-service/metrics/balance.go b/op-service/metrics/balance.go new file mode 100644 index 0000000000000..de9066846c5e2 --- /dev/null +++ b/op-service/metrics/balance.go @@ -0,0 +1,59 @@ +package metrics + +import ( + "context" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" +) + +// weiToEther divides the wei value by 10^18 to get a number in ether as a float64 +func weiToEther(wei *big.Int) float64 { + num := new(big.Rat).SetInt(wei) + denom := big.NewRat(params.Ether, 1) + num = num.Quo(num, denom) + f, _ := num.Float64() + return f +} + +// LaunchBalanceMetrics fires off a go rountine that queries the balance of the supplied account & periodically records it +// to the balance metric of the namespace. The balance of the account is recorded in Ether (not Wei). +// Cancel the supplied context to shut down the go routine +func LaunchBalanceMetrics(ctx context.Context, log log.Logger, r *prometheus.Registry, ns string, client *ethclient.Client, account common.Address) { + go func() { + balanceGuage := promauto.With(r).NewGauge(prometheus.GaugeOpts{ + Namespace: ns, + Name: "balance", + Help: "balance (in ether) of account " + account.String(), + }) + + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) + bigBal, err := client.BalanceAt(ctx, account, nil) + if err != nil { + log.Warn("failed to get balance of account", "err", err, "address", account) + cancel() + continue + } + bal := weiToEther(bigBal) + balanceGuage.Set(bal) + cancel() + case <-ctx.Done(): + log.Info("balance metrics shutting down") + return + } + } + + }() +} diff --git a/op-service/metrics/balance_test.go b/op-service/metrics/balance_test.go new file mode 100644 index 0000000000000..e8d0122608c9a --- /dev/null +++ b/op-service/metrics/balance_test.go @@ -0,0 +1,40 @@ +package metrics + +import ( + "math/big" + "testing" +) + +type weiToEthTestCase struct { + input *big.Int + output float64 +} + +func TestWeiToEther(t *testing.T) { + tests := []weiToEthTestCase{ + { + input: big.NewInt(1_000_000_000_000_000_000), + output: 1.0, + }, + { + input: big.NewInt(3_000_000_000_000_000_000), + output: 3.0, + }, + { + input: big.NewInt(3_456_789_000_000_000_000), + output: 3.456789, + }, + { + input: new(big.Int).Mul(big.NewInt(1_000_000), big.NewInt(1_000_000_000_000_000_000)), + output: 1_000_000, + }, + } + + for i, tc := range tests { + out := weiToEther(tc.input) + if out != tc.output { + t.Fatalf("test %v: expected %v but got %v", i, tc.output, out) + } + } + +} diff --git a/ops-bedrock/docker-compose.yml b/ops-bedrock/docker-compose.yml index 6a33e2e3af088..80335f9340a46 100644 --- a/ops-bedrock/docker-compose.yml +++ b/ops-bedrock/docker-compose.yml @@ -86,6 +86,7 @@ services: dockerfile: ./op-proposer/Dockerfile ports: - "6062:6060" + - "7302:7300" environment: OP_PROPOSER_L1_ETH_RPC: http://l1:8545 OP_PROPOSER_L2_ETH_RPC: http://l2:8545 @@ -99,6 +100,7 @@ services: OP_PROPOSER_LOG_TERMINAL: "true" OP_PROPOSER_L2OO_ADDRESS: "${L2OO_ADDRESS}" OP_PROPOSER_PPROF_ENABLED: "true" + OP_PROPOSER_METRICS_ENABLED: "true" op-batcher: depends_on: @@ -110,6 +112,7 @@ services: dockerfile: ./op-batcher/Dockerfile ports: - "6061:6060" + - "7301:7300" environment: OP_BATCHER_L1_ETH_RPC: http://l1:8545 OP_BATCHER_L2_ETH_RPC: http://l2:8545 @@ -127,6 +130,7 @@ services: OP_BATCHER_SEQUENCER_BATCH_INBOX_ADDRESS: "${SEQUENCER_BATCH_INBOX_ADDRESS}" OP_BATCHER_LOG_TERMINAL: "true" OP_BATCHER_PPROF_ENABLED: "true" + OP_BATCHER_METRICS_ENABLED: "true" stateviz: build: diff --git a/ops/docker/ci-builder/Dockerfile b/ops/docker/ci-builder/Dockerfile index 883352ab2e0e0..7ecdb0de18296 100644 --- a/ops/docker/ci-builder/Dockerfile +++ b/ops/docker/ci-builder/Dockerfile @@ -48,7 +48,7 @@ RUN apt-get update && \ apt-get install -y nodejs && \ npm i -g yarn && \ npm i -g depcheck && \ - pip install slither-analyzer && \ + pip install slither-analyzer==0.9.0 && \ go install gotest.tools/gotestsum@latest && \ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.48.0 && \ curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | bash && \ diff --git a/package.json b/package.json index ee21b2580ba9b..7f9c2ffef1c2a 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "ops/docker/ci-builder", "ops/docker/foundry", "proxyd", - "teleportr" + "teleportr", + "endpoint-monitor" ], "nohoist": [ "**/typechain/*", diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index 13120c47c554d..902943277251b 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -6,9 +6,11 @@ GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 1122 GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 348094) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 112225) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 40569) -GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 68671) +GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 68693) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 74964) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35777) +CrossDomainMessenger_Test:testFuzz_baseGas(uint32) (runs: 256, μ: 20263, ~: 20263) +CrossDomainMessenger_Test:test_baseGas() (gas: 20100) CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner() (gas: 61850) CrossDomainOwnable_Test:test_onlyOwner() (gas: 34945) CrossDomainOwnable_Test:test_revertOnlyOwner() (gas: 10619) @@ -54,33 +56,34 @@ L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24537) L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24562) L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24716) L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 48043) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 197182) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 190790) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 73561) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 197171) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 190779) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 73559) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 65858) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageV0Fails() (gas: 33272) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageV0Fails() (gas: 33258) L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60526) L1CrossDomainMessenger_Test:test_L1MessengerReplayMessageWithValue() (gas: 38193) -L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 299481) +L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 299487) L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1490366) L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 41003) L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24283) -L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 81947) -L1StandardBridge_Test:test_depositERC20() (gas: 573393) -L1StandardBridge_Test:test_depositERC20To() (gas: 575512) -L1StandardBridge_Test:test_depositETH() (gas: 367613) -L1StandardBridge_Test:test_depositETHTo() (gas: 324750) -L1StandardBridge_Test:test_finalizeBridgeETH_incorrectValueReverts() (gas: 34246) -L1StandardBridge_Test:test_finalizeBridgeETH_sendToMessengerReverts() (gas: 34325) -L1StandardBridge_Test:test_finalizeBridgeETH_sendToSelfReverts() (gas: 34284) -L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 484456) -L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 58729) -L1StandardBridge_Test:test_initialize() (gas: 22082) -L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 22420) -L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 40793) -L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 31579) -L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 31188) -L1StandardBridge_Test:test_receive() (gas: 514254) +L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 81945) +L1StandardBridge_DepositERC20To_Test:test_depositERC20To_success() (gas: 575569) +L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 573459) +L1StandardBridge_DepositERC20_TestFail:test_depositERC20_revert_notEoa() (gas: 22343) +L1StandardBridge_DepositETHTo_Test:test_depositETHTo() (gas: 324679) +L1StandardBridge_DepositETH_Test:test_depositETH_success() (gas: 367526) +L1StandardBridge_DepositETH_TestFail:test_DepositETH_revert_notEoa() (gas: 40759) +L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_revert_incorrectValue() (gas: 34218) +L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_revert_sendToMessenger() (gas: 34301) +L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_revert_sendToSelf() (gas: 34268) +L1StandardBridge_FinalizeERC20Withdrawal_Test:test_finalizeERC20Withdrawal() (gas: 484497) +L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_revert_notMessenger() (gas: 31210) +L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_revert_notOtherBridge() (gas: 31557) +L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal() (gas: 58670) +L1StandardBridge_Getter_Test:test_getters_success() (gas: 29470) +L1StandardBridge_Initialize_Test:test_initialize_success() (gas: 22061) +L1StandardBridge_Receive_Test:test_receive_success() (gas: 514247) L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10860) L2CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 167641) L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8411) @@ -90,33 +93,33 @@ L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 53115) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 36217) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageV0Fails() (gas: 18871) L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41637) -L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 120636) +L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 120648) L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 136338) L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10576) L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 50459) -L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 26829) -L2OutputOracleTest:testCannot_constructWithBadTimestamp() (gas: 52842) -L2OutputOracleTest:testCannot_deleteL2Output_ifNotOwner() (gas: 25123) -L2OutputOracleTest:testCannot_deleteL2Output_withWrongRoot() (gas: 91467) -L2OutputOracleTest:testCannot_deleteL2Output_withWrongTime() (gas: 87450) -L2OutputOracleTest:testCannot_proposeEmptyOutput() (gas: 24150) -L2OutputOracleTest:testCannot_proposeFutureTimetamp() (gas: 26074) -L2OutputOracleTest:testCannot_proposeL2OutputIfNotProposer() (gas: 23564) -L2OutputOracleTest:testCannot_proposeOnWrongFork() (gas: 26381) -L2OutputOracleTest:testCannot_proposeUnexpectedBlockNumber() (gas: 26005) -L2OutputOracleTest:test_changeProposer() (gas: 56127) -L2OutputOracleTest:test_computeL2Timestamp() (gas: 30284) -L2OutputOracleTest:test_constructor() (gas: 49046) -L2OutputOracleTest:test_deleteOutput() (gas: 77260) -L2OutputOracleTest:test_getL2Output() (gas: 88523) -L2OutputOracleTest:test_latestBlockNumber() (gas: 76242) +L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 26828) +L2OutputOracleTest:testCannot_constructWithBadTimestamp() (gas: 52850) +L2OutputOracleTest:testCannot_deleteL2Output_ifNotOwner() (gas: 25145) +L2OutputOracleTest:testCannot_deleteL2Output_withWrongRoot() (gas: 91488) +L2OutputOracleTest:testCannot_deleteL2Output_withWrongTime() (gas: 87471) +L2OutputOracleTest:testCannot_proposeEmptyOutput() (gas: 24149) +L2OutputOracleTest:testCannot_proposeFutureTimetamp() (gas: 26073) +L2OutputOracleTest:testCannot_proposeL2OutputIfNotProposer() (gas: 23563) +L2OutputOracleTest:testCannot_proposeOnWrongFork() (gas: 26380) +L2OutputOracleTest:testCannot_proposeUnexpectedBlockNumber() (gas: 26004) +L2OutputOracleTest:test_changeProposer() (gas: 56149) +L2OutputOracleTest:test_computeL2Timestamp() (gas: 30192) +L2OutputOracleTest:test_constructor() (gas: 49090) +L2OutputOracleTest:test_deleteOutput() (gas: 77312) +L2OutputOracleTest:test_getL2Output() (gas: 88610) +L2OutputOracleTest:test_latestBlockNumber() (gas: 76241) L2OutputOracleTest:test_nextBlockNumber() (gas: 15254) -L2OutputOracleTest:test_proposeWithBlockhashAndHeight() (gas: 75046) -L2OutputOracleTest:test_proposingAnotherOutput() (gas: 76903) -L2OutputOracleTest:test_updateOwner() (gas: 46095) -L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 19555) -L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 24554) -L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 39086) +L2OutputOracleTest:test_proposeWithBlockhashAndHeight() (gas: 75045) +L2OutputOracleTest:test_proposingAnotherOutput() (gas: 76902) +L2OutputOracleTest:test_updateOwner() (gas: 46161) +L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 17381) +L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 22377) +L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 39108) L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 180632) L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21816) L2StandardBridge_Test:test_finalizeBridgeETH_incorrectValueReverts() (gas: 23835) @@ -159,16 +162,16 @@ OptimismPortalUpgradeable_Test:test_cannotInitImpl() (gas: 10813) OptimismPortalUpgradeable_Test:test_cannotInitProxy() (gas: 15789) OptimismPortalUpgradeable_Test:test_initValuesOnProxy() (gas: 15967) OptimismPortalUpgradeable_Test:test_upgrading() (gas: 180632) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_differential(address,address,uint256,uint256,bytes) (runs: 256, μ: 258364, ~: 259036) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_differential(address,address,uint256,uint256,bytes) (runs: 256, μ: 258442, ~: 259036) OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnInsufficientGas() (gas: 158312) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnInvalidOutputRootProof() (gas: 81265) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnInvalidOutputRootProof() (gas: 81287) OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnRecentWithdrawal() (gas: 50525) OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnReentrancy() (gas: 202902) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnReplay() (gas: 278777) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnReplay() (gas: 278821) OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnSelfCall() (gas: 50563) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOninvalidWithdrawalProof() (gas: 148586) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_succeeds() (gas: 186825) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails() (gas: 289474) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOninvalidWithdrawalProof() (gas: 148608) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_succeeds() (gas: 186847) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails() (gas: 289496) OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17341) OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 14199) OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 127534) @@ -180,7 +183,7 @@ OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreat OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 75881) OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 83333) OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 83993) -OptimismPortal_Test:test_isBlockFinalized() (gas: 113744) +OptimismPortal_Test:test_isBlockFinalized() (gas: 113897) OptimismPortal_Test:test_simple_isBlockFinalized() (gas: 24130) Proxy_Test:test_clashingFunctionSignatures() (gas: 101427) Proxy_Test:test_implementationKey() (gas: 20942) diff --git a/packages/contracts-bedrock/.prettierignore b/packages/contracts-bedrock/.prettierignore index 48994f2effc5f..a9eeca2bb1c78 100644 --- a/packages/contracts-bedrock/.prettierignore +++ b/packages/contracts-bedrock/.prettierignore @@ -1,7 +1,6 @@ # Deps and test files node_modules lib -contracts/test/*.t.sol contracts/vendor/*.sol # build output diff --git a/packages/contracts-bedrock/.storage-layout b/packages/contracts-bedrock/.storage-layout index 3b6042ad94245..020a6d2ff2583 100644 --- a/packages/contracts-bedrock/.storage-layout +++ b/packages/contracts-bedrock/.storage-layout @@ -97,11 +97,11 @@ |----------------------+----------------------------------------+------+--------+-------+------------------------------------------------| | params | struct ResourceMetering.ResourceParams | 1 | 0 | 32 | contracts/L1/OptimismPortal.sol:OptimismPortal | |----------------------+----------------------------------------+------+--------+-------+------------------------------------------------| -| __gap | uint256[49] | 2 | 0 | 1568 | contracts/L1/OptimismPortal.sol:OptimismPortal | +| __gap | uint256[48] | 2 | 0 | 1536 | contracts/L1/OptimismPortal.sol:OptimismPortal | |----------------------+----------------------------------------+------+--------+-------+------------------------------------------------| -| l2Sender | address | 51 | 0 | 20 | contracts/L1/OptimismPortal.sol:OptimismPortal | +| l2Sender | address | 50 | 0 | 20 | contracts/L1/OptimismPortal.sol:OptimismPortal | |----------------------+----------------------------------------+------+--------+-------+------------------------------------------------| -| finalizedWithdrawals | mapping(bytes32 => bool) | 52 | 0 | 32 | contracts/L1/OptimismPortal.sol:OptimismPortal | +| finalizedWithdrawals | mapping(bytes32 => bool) | 51 | 0 | 32 | contracts/L1/OptimismPortal.sol:OptimismPortal | +----------------------+----------------------------------------+------+--------+-------+------------------------------------------------+ ======================= diff --git a/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol b/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol index cabe905c3a803..7e348bf7d2ae5 100644 --- a/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol @@ -138,7 +138,27 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { STARTING_TIMESTAMP = _startingTimestamp; L2_BLOCK_TIME = _l2BlockTime; - initialize(_genesisL2Output, _startingBlockNumber, _proposer, _owner); + initialize(_genesisL2Output, _proposer, _owner); + } + + /** + * @notice Initializer. + * + * @param _genesisL2Output The initial L2 output of the L2 chain. + * @param _proposer The address of the proposer. + * @param _owner The address of the owner. + */ + function initialize( + bytes32 _genesisL2Output, + address _proposer, + address _owner + ) public initializer { + require(_proposer != _owner, "L2OutputOracle: proposer cannot be the same as the owner"); + l2Outputs[STARTING_BLOCK_NUMBER] = Types.OutputProposal(_genesisL2Output, block.timestamp); + latestBlockNumber = STARTING_BLOCK_NUMBER; + __Ownable_init(); + changeProposer(_proposer); + _transferOwnership(_owner); } /** @@ -257,28 +277,6 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { return output; } - /** - * @notice Initializer. - * - * @param _genesisL2Output The initial L2 output of the L2 chain. - * @param _startingBlockNumber The timestamp to start L2 block at. - * @param _proposer The address of the proposer. - * @param _owner The address of the owner. - */ - function initialize( - bytes32 _genesisL2Output, - uint256 _startingBlockNumber, - address _proposer, - address _owner - ) public initializer { - require(_proposer != _owner, "L2OutputOracle: proposer cannot be the same as the owner"); - l2Outputs[_startingBlockNumber] = Types.OutputProposal(_genesisL2Output, block.timestamp); - latestBlockNumber = _startingBlockNumber; - __Ownable_init(); - changeProposer(_proposer); - _transferOwnership(_owner); - } - /** * @notice Overrides the standard implementation of transferOwnership * to add the requirement that the owner and proposer are distinct. diff --git a/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol b/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol index 967ed26b78bc9..29b80932fe6c4 100644 --- a/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol +++ b/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { SafeCall } from "../libraries/SafeCall.sol"; import { L2OutputOracle } from "./L2OutputOracle.sol"; import { Types } from "../libraries/Types.sol"; diff --git a/packages/contracts-bedrock/contracts/L1/ResourceMetering.sol b/packages/contracts-bedrock/contracts/L1/ResourceMetering.sol index e7932c4eb8c5f..8a0a0870329b1 100644 --- a/packages/contracts-bedrock/contracts/L1/ResourceMetering.sol +++ b/packages/contracts-bedrock/contracts/L1/ResourceMetering.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { SignedMath } from "@openzeppelin/contracts/utils/math/SignedMath.sol"; import { FixedPointMathLib } from "@rari-capital/solmate/src/utils/FixedPointMathLib.sol"; @@ -62,7 +62,7 @@ abstract contract ResourceMetering is Initializable { /** * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades. */ - uint256[49] private __gap; + uint256[48] private __gap; /** * @notice Meters access to a function based an amount of a requested resource. diff --git a/packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol b/packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol index c5be39247d742..df8feec8bad72 100644 --- a/packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol +++ b/packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol @@ -40,7 +40,7 @@ contract L2ToL1MessagePasser is Semver { * @param gasLimit The minimum amount of gas that must be provided when withdrawing on L1. * @param data The data to be forwarded to the target on L1. */ - event WithdrawalInitiated( + event MessagePassed( uint256 indexed nonce, address indexed sender, address indexed target, @@ -51,11 +51,11 @@ contract L2ToL1MessagePasser is Semver { /** * @notice Emitted any time a withdrawal is initiated. An extension to - * WithdrawalInitiated so that the interface is maintained. + * MessagePassed to allow for a 4th indexed argument. * * @param hash The hash of the withdrawal */ - event WithdrawalInitiatedExtension1(bytes32 indexed hash); + event MessagePassedExtension1(bytes32 indexed hash); /** * @notice Emitted when the balance of this contract is burned. @@ -113,8 +113,8 @@ contract L2ToL1MessagePasser is Semver { sentMessages[withdrawalHash] = true; - emit WithdrawalInitiated(nonce, msg.sender, _target, msg.value, _gasLimit, _data); - emit WithdrawalInitiatedExtension1(withdrawalHash); + emit MessagePassed(nonce, msg.sender, _target, msg.value, _gasLimit, _data); + emit MessagePassedExtension1(withdrawalHash); unchecked { ++nonce; diff --git a/packages/contracts-bedrock/contracts/test/CommonTest.t.sol b/packages/contracts-bedrock/contracts/test/CommonTest.t.sol index a6a6ed856a5f7..b8b23e433cef6 100644 --- a/packages/contracts-bedrock/contracts/test/CommonTest.t.sol +++ b/packages/contracts-bedrock/contracts/test/CommonTest.t.sol @@ -130,22 +130,20 @@ contract L2OutputOracle_Initializer is CommonTest { vm.prank(multisig); proxy.upgradeToAndCall( address(oracleImpl), - abi.encodeWithSelector( - L2OutputOracle.initialize.selector, - genesisL2Output, - startingBlockNumber, - proposer, - owner + abi.encodeCall( + L2OutputOracle.initialize, + ( + genesisL2Output, + proposer, + owner + ) ) ); oracle = L2OutputOracle(address(proxy)); vm.label(address(oracle), "L2OutputOracle"); // Set the L2ToL1MessagePasser at the correct address - vm.etch( - Predeploys.L2_TO_L1_MESSAGE_PASSER, - address(new L2ToL1MessagePasser()).code - ); + vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code); vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser"); } @@ -185,12 +183,9 @@ contract Messenger_Initializer is L2OutputOracle_Initializer { uint256 gasLimit ); - event SentMessageExtension1( - address indexed sender, - uint256 value - ); + event SentMessageExtension1(address indexed sender, uint256 value); - event WithdrawalInitiated( + event MessagePassed( uint256 indexed nonce, address indexed sender, address indexed target, @@ -273,12 +268,7 @@ contract Bridge_Initializer is Messenger_Initializer { ERC20 BadL2Token; OptimismMintableERC20 RemoteL1Token; - event ETHDepositInitiated( - address indexed from, - address indexed to, - uint256 amount, - bytes data - ); + event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data); event ETHWithdrawalFinalized( address indexed from, @@ -332,19 +322,9 @@ contract Bridge_Initializer is Messenger_Initializer { bytes data ); - event ETHBridgeInitiated( - address indexed from, - address indexed to, - uint256 amount, - bytes data - ); + event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data); - event ETHBridgeFinalized( - address indexed from, - address indexed to, - uint256 amount, - bytes data - ); + event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data); event ERC20BridgeInitiated( address indexed localToken, @@ -364,15 +344,6 @@ contract Bridge_Initializer is Messenger_Initializer { bytes data ); - event ERC20BridgeFailed( - address indexed localToken, - address indexed remoteToken, - address indexed from, - address to, - uint256 amount, - bytes data - ); - function setUp() public virtual override { super.setUp(); @@ -409,9 +380,7 @@ contract Bridge_Initializer is Messenger_Initializer { Predeploys.L2_STANDARD_BRIDGE ); vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code); - L2TokenFactory = OptimismMintableERC20Factory( - Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY - ); + L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY); vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code); @@ -580,9 +549,10 @@ contract FFIInterface is Test { return abi.decode(result, (bytes32)); } - function encodeDepositTransaction( - Types.UserDepositTransaction calldata txn - ) external returns (bytes memory) { + function encodeDepositTransaction(Types.UserDepositTransaction calldata txn) + external + returns (bytes memory) + { string[] memory cmds = new string[](12); cmds[0] = "node"; cmds[1] = "dist/scripts/differential-testing.js"; @@ -660,18 +630,19 @@ contract Reverter { // Useful for testing reentrancy guards contract CallerCaller { - event WhatHappened( - bool success, - bytes returndata - ); + event WhatHappened(bool success, bytes returndata); fallback() external { (bool success, bytes memory returndata) = msg.sender.call(msg.data); emit WhatHappened(success, returndata); assembly { switch success - case 0 { revert(add(returndata, 0x20), mload(returndata)) } - default { return(add(returndata, 0x20), mload(returndata)) } + case 0 { + revert(add(returndata, 0x20), mload(returndata)) + } + default { + return(add(returndata, 0x20), mload(returndata)) + } } } } diff --git a/packages/contracts-bedrock/contracts/test/CrossDomainMessenger.t.sol b/packages/contracts-bedrock/contracts/test/CrossDomainMessenger.t.sol new file mode 100644 index 0000000000000..a49f08c6b302f --- /dev/null +++ b/packages/contracts-bedrock/contracts/test/CrossDomainMessenger.t.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Messenger_Initializer, Reverter, CallerCaller } from "./CommonTest.t.sol"; + +// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2 +// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract. +contract CrossDomainMessenger_Test is Messenger_Initializer { + // Ensure that baseGas passes for the max value of _minGasLimit, + // this is about 4 Billion. + function test_baseGas() external { + L1Messenger.baseGas(hex"ff", type(uint32).max); + } + + // Fuzz for other values which might cause a revert in baseGas. + function testFuzz_baseGas(uint32 _minGasLimit) external { + L1Messenger.baseGas(hex"ff", _minGasLimit); + } +} diff --git a/packages/contracts-bedrock/contracts/test/CrossDomainOwnable.t.sol b/packages/contracts-bedrock/contracts/test/CrossDomainOwnable.t.sol index 221b8cc9d83fd..ffb1e1d46d74b 100644 --- a/packages/contracts-bedrock/contracts/test/CrossDomainOwnable.t.sol +++ b/packages/contracts-bedrock/contracts/test/CrossDomainOwnable.t.sol @@ -30,17 +30,11 @@ contract CrossDomainOwnable_Test is CommonTest { // Check that making a call can set the value properly function test_onlyOwner() external { - assertEq( - setter.value(), - 0 - ); + assertEq(setter.value(), 0); vm.prank(AddressAliasHelper.applyL1ToL2Alias(setter.owner())); setter.set(1); - assertEq( - setter.value(), - 1 - ); + assertEq(setter.value(), 1); } } @@ -63,10 +57,7 @@ contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer { 0, 10000, false, - abi.encodeWithSelector( - XDomainSetter.set.selector, - 1 - ) + abi.encodeWithSelector(XDomainSetter.set.selector, 1) ); // Simulate the operation of the `op-node` by parsing data @@ -79,19 +70,13 @@ contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer { // It is the expected topic bytes32 topic = log.topics[0]; - assertEq( - topic, - keccak256("TransactionDeposited(address,address,uint256,bytes)") - ); + assertEq(topic, keccak256("TransactionDeposited(address,address,uint256,bytes)")); // from is indexed and the first argument to the event. bytes32 _from = log.topics[1]; address from = Bytes32AddressLib.fromLast20Bytes(_from); - assertEq( - AddressAliasHelper.undoL1ToL2Alias(from), - alice - ); + assertEq(AddressAliasHelper.undoL1ToL2Alias(from), alice); // Make a call from the "from" value received from the log. // In theory the opaque data could be parsed from the log @@ -99,9 +84,6 @@ contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer { // directly on the setter is good enough. vm.prank(from); setter.set(1); - assertEq( - setter.value(), - 1 - ); + assertEq(setter.value(), 1); } } diff --git a/packages/contracts-bedrock/contracts/test/CrossDomainOwnable2.t.sol b/packages/contracts-bedrock/contracts/test/CrossDomainOwnable2.t.sol index a6017bcbc37fa..13998a5ed30b5 100644 --- a/packages/contracts-bedrock/contracts/test/CrossDomainOwnable2.t.sol +++ b/packages/contracts-bedrock/contracts/test/CrossDomainOwnable2.t.sol @@ -19,7 +19,7 @@ contract XDomainSetter2 is CrossDomainOwnable2 { contract CrossDomainOwnable2_Test is Messenger_Initializer { XDomainSetter2 setter; - function setUp() override public { + function setUp() public override { super.setUp(); vm.prank(alice); setter = new XDomainSetter2(); @@ -47,10 +47,7 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer { address target = address(setter); uint256 value = 0; uint256 minGasLimit = 0; - bytes memory message = abi.encodeWithSelector( - XDomainSetter2.set.selector, - 1 - ); + bytes memory message = abi.encodeWithSelector(XDomainSetter2.set.selector, 1); bytes32 hash = Hashing.hashCrossDomainMessage( Encoding.encodeVersionedNonce(nonce, 1), @@ -76,10 +73,7 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer { message ); - assertEq( - setter.value(), - 0 - ); + assertEq(setter.value(), 0); } function test_onlyOwner() external { @@ -94,15 +88,9 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer { address(setter), 0, 0, - abi.encodeWithSelector( - XDomainSetter2.set.selector, - 2 - ) + abi.encodeWithSelector(XDomainSetter2.set.selector, 2) ); - assertEq( - setter.value(), - 2 - ); + assertEq(setter.value(), 2); } } diff --git a/packages/contracts-bedrock/contracts/test/DeployerWhitelist.t.sol b/packages/contracts-bedrock/contracts/test/DeployerWhitelist.t.sol index eed7fe8d3fd79..50b1882b7d095 100644 --- a/packages/contracts-bedrock/contracts/test/DeployerWhitelist.t.sol +++ b/packages/contracts-bedrock/contracts/test/DeployerWhitelist.t.sol @@ -21,9 +21,6 @@ contract DeployerWhitelist_Test is CommonTest { vm.prank(list.owner()); list.setOwner(address(1)); - assertEq( - bytes32(uint256(1)), - vm.load(address(list), bytes32(uint256(0))) - ); + assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0)))); } } diff --git a/packages/contracts-bedrock/contracts/test/Encoding.t.sol b/packages/contracts-bedrock/contracts/test/Encoding.t.sol index c21fad77c4a99..c20a02d7f58a3 100644 --- a/packages/contracts-bedrock/contracts/test/Encoding.t.sol +++ b/packages/contracts-bedrock/contracts/test/Encoding.t.sol @@ -22,15 +22,9 @@ contract Encoding_Test is CommonTest { uint256 nonce = uint256(Encoding.encodeVersionedNonce(_nonce, _version)); (uint256 decodedNonce, uint256 decodedVersion) = ffi.decodeVersionedNonce(nonce); - assertEq( - _version, - uint16(decodedVersion) - ); + assertEq(_version, uint16(decodedVersion)); - assertEq( - _nonce, - uint240(decodedNonce) - ); + assertEq(_nonce, uint240(decodedNonce)); } function test_encodeCrossDomainMessage_differential( @@ -91,9 +85,6 @@ contract Encoding_Test is CommonTest { bytes memory txn = Encoding.encodeDepositTransaction(t); bytes memory _txn = ffi.encodeDepositTransaction(t); - assertEq( - txn, - _txn - ); + assertEq(txn, _txn); } } diff --git a/packages/contracts-bedrock/contracts/test/GasPriceOracle.t.sol b/packages/contracts-bedrock/contracts/test/GasPriceOracle.t.sol index acd8fe32b6b65..fac223bc173b7 100644 --- a/packages/contracts-bedrock/contracts/test/GasPriceOracle.t.sol +++ b/packages/contracts-bedrock/contracts/test/GasPriceOracle.t.sol @@ -7,7 +7,6 @@ import { L1Block } from "../L2/L1Block.sol"; import { Predeploys } from "../libraries/Predeploys.sol"; contract GasPriceOracle_Test is CommonTest { - event OverheadUpdated(uint256); event ScalarUpdated(uint256); event DecimalsUpdated(uint256); @@ -18,10 +17,7 @@ contract GasPriceOracle_Test is CommonTest { function setUp() external { // place the L1Block contract at the predeploy address - vm.etch( - Predeploys.L1_BLOCK_ATTRIBUTES, - address(new L1Block()).code - ); + vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code); l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES); depositor = l1Block.DEPOSITOR_ACCOUNT(); @@ -39,13 +35,7 @@ contract GasPriceOracle_Test is CommonTest { uint64 sequenceNumber = 0; vm.prank(depositor); - l1Block.setL1BlockValues( - number, - timestamp, - basefee, - hash, - sequenceNumber - ); + l1Block.setL1BlockValues(number, timestamp, basefee, hash, sequenceNumber); } function test_owner() external { @@ -57,26 +47,17 @@ contract GasPriceOracle_Test is CommonTest { // the overhead is at slot 3 vm.prank(gasOracle.owner()); gasOracle.setOverhead(456); - assertEq( - 456, - uint256(vm.load(address(gasOracle), bytes32(uint256(3)))) - ); + assertEq(456, uint256(vm.load(address(gasOracle), bytes32(uint256(3))))); // scalar is at slot 4 vm.prank(gasOracle.owner()); gasOracle.setScalar(333); - assertEq( - 333, - uint256(vm.load(address(gasOracle), bytes32(uint256(4)))) - ); + assertEq(333, uint256(vm.load(address(gasOracle), bytes32(uint256(4))))); // decimals is at slot 5 vm.prank(gasOracle.owner()); gasOracle.setDecimals(222); - assertEq( - 222, - uint256(vm.load(address(gasOracle), bytes32(uint256(5)))) - ); + assertEq(222, uint256(vm.load(address(gasOracle), bytes32(uint256(5))))); } function test_l1BaseFee() external { @@ -99,10 +80,7 @@ contract GasPriceOracle_Test is CommonTest { function test_setGasPriceReverts() external { vm.prank(gasOracle.owner()); (bool success, bytes memory returndata) = address(gasOracle).call( - abi.encodeWithSignature( - "setGasPrice(uint256)", - 1 - ) + abi.encodeWithSignature("setGasPrice(uint256)", 1) ); assertEq(success, false); @@ -112,10 +90,7 @@ contract GasPriceOracle_Test is CommonTest { function test_setL1BaseFeeReverts() external { vm.prank(gasOracle.owner()); (bool success, bytes memory returndata) = address(gasOracle).call( - abi.encodeWithSignature( - "setL1BaseFee(uint256)", - 1 - ) + abi.encodeWithSignature("setL1BaseFee(uint256)", 1) ); assertEq(success, false); diff --git a/packages/contracts-bedrock/contracts/test/Hashing.t.sol b/packages/contracts-bedrock/contracts/test/Hashing.t.sol index adc32958f8003..a6025ea57d69a 100644 --- a/packages/contracts-bedrock/contracts/test/Hashing.t.sol +++ b/packages/contracts-bedrock/contracts/test/Hashing.t.sol @@ -17,10 +17,7 @@ contract Hashing_Test is CommonTest { 0x1 ); - assertEq( - sourceHash, - 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc - ); + assertEq(sourceHash, 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc); } function test_hashCrossDomainMessage_differential( @@ -65,24 +62,10 @@ contract Hashing_Test is CommonTest { bytes memory _data ) external { bytes32 hash = Hashing.hashWithdrawal( - Types.WithdrawalTransaction( - _nonce, - _sender, - _target, - _value, - _gasLimit, - _data - ) + Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data) ); - bytes32 _hash = ffi.hashWithdrawal( - _nonce, - _sender, - _target, - _value, - _gasLimit, - _data - ); + bytes32 _hash = ffi.hashWithdrawal(_nonce, _sender, _target, _value, _gasLimit, _data); assertEq(hash, _hash); } diff --git a/packages/contracts-bedrock/contracts/test/L1Block.t.sol b/packages/contracts-bedrock/contracts/test/L1Block.t.sol index b96e909a3a774..ad2a95e9b48af 100644 --- a/packages/contracts-bedrock/contracts/test/L1Block.t.sol +++ b/packages/contracts-bedrock/contracts/test/L1Block.t.sol @@ -16,7 +16,13 @@ contract L1BlockTest is CommonTest { lb.setL1BlockValues(uint64(1), uint64(2), 3, NON_ZERO_HASH, uint64(4)); } - function test_updatesValues(uint64 n, uint64 t, uint256 b, bytes32 h, uint64 s) external { + function test_updatesValues( + uint64 n, + uint64 t, + uint256 b, + bytes32 h, + uint64 s + ) external { vm.prank(depositor); lb.setL1BlockValues(n, t, b, h, s); assertEq(lb.number(), n); @@ -48,6 +54,12 @@ contract L1BlockTest is CommonTest { function test_updateValues() external { vm.prank(depositor); - lb.setL1BlockValues(type(uint64).max, type(uint64).max, type(uint256).max, keccak256(abi.encode(1)), type(uint64).max); + lb.setL1BlockValues( + type(uint64).max, + type(uint64).max, + type(uint256).max, + keccak256(abi.encode(1)), + type(uint64).max + ); } } diff --git a/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol b/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol index 540eacd21dfed..bc10b1a7f741c 100644 --- a/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol @@ -22,6 +22,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { // Receiver address for testing address recipient = address(0xabbaacdc); + // Storage slot of the l2Sender + uint256 constant senderSlotIndex = 50; + function setUp() public override { super.setUp(); } @@ -138,11 +141,12 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; // set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - uint256 senderSlotIndex = 51; vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.prank(address(op)); - vm.expectRevert("CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade"); + vm.expectRevert( + "CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade" + ); L1Messenger.relayMessage( 0, // nonce sender, @@ -161,13 +165,19 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { vm.expectCall(target, hex"1111"); // set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - uint256 senderSlotIndex = 51; vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.prank(address(op)); vm.expectEmit(true, true, true, true); - bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, hex"1111"); + bytes32 hash = Hashing.hashCrossDomainMessage( + Encoding.encodeVersionedNonce(0, 1), + sender, + target, + 0, + 0, + hex"1111" + ); emit RelayedMessage(hash); @@ -195,11 +205,25 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { vm.prank(address(op)); vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); - L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message); + L1Messenger.relayMessage( + Encoding.encodeVersionedNonce(0, 1), + sender, + target, + 0, + 0, + message + ); vm.store(address(op), 0, bytes32(abi.encode(sender))); vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); - L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message); + L1Messenger.relayMessage( + Encoding.encodeVersionedNonce(0, 1), + sender, + target, + 0, + 0, + message + ); } // relayMessage: should revert if eth is sent from a contract other than the standard bridge @@ -211,7 +235,14 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { vm.expectRevert( "CrossDomainMessenger: value must be zero unless message is from a system address" ); - L1Messenger.relayMessage{ value: 100 }(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message); + L1Messenger.relayMessage{ value: 100 }( + Encoding.encodeVersionedNonce(0, 1), + sender, + target, + 0, + 0, + message + ); } // relayMessage: the xDomainMessageSender is reset to the original value @@ -221,11 +252,16 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; - uint256 senderSlotIndex = 51; - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.prank(address(op)); - L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), address(0), address(0), 0, 0, hex""); + L1Messenger.relayMessage( + Encoding.encodeVersionedNonce(0, 1), + address(0), + address(0), + 0, + 0, + hex"" + ); vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); L1Messenger.xDomainMessageSender(); @@ -249,14 +285,20 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { vm.expectCall(target, hex"1111"); - bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, value, 0, hex"1111"); + bytes32 hash = Hashing.hashCrossDomainMessage( + Encoding.encodeVersionedNonce(0, 1), + sender, + target, + value, + 0, + hex"1111" + ); - uint256 senderSlotIndex = 51; vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.etch(target, address(new Reverter()).code); vm.deal(address(op), value); vm.prank(address(op)); - L1Messenger.relayMessage{value: value}( + L1Messenger.relayMessage{ value: value }( Encoding.encodeVersionedNonce(0, 1), // nonce sender, target, @@ -305,15 +347,24 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { hex"1111" ); - bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message); + bytes32 hash = Hashing.hashCrossDomainMessage( + Encoding.encodeVersionedNonce(0, 1), + sender, + target, + 0, + 0, + message + ); - uint256 senderSlotIndex = 51; vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.etch(target, address(new CallerCaller()).code); vm.expectEmit(true, true, true, true, target); - emit WhatHappened(false, abi.encodeWithSignature("Error(string)", "ReentrancyGuard: reentrant call")); + emit WhatHappened( + false, + abi.encodeWithSignature("Error(string)", "ReentrancyGuard: reentrant call") + ); vm.prank(address(op)); vm.expectCall(target, message); diff --git a/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol b/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol index 2a2ab81209be8..9804c1f4d0bb5 100644 --- a/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol @@ -10,33 +10,31 @@ import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { stdStorage, StdStorage } from "forge-std/Test.sol"; -contract L1StandardBridge_Test is Bridge_Initializer { - using stdStorage for StdStorage; - - function setUp() public override { - super.setUp(); +contract L1StandardBridge_Getter_Test is Bridge_Initializer { + function test_getters_success() external { + assert(L1Bridge.l2TokenBridge() == address(L2Bridge)); + assert(L1Bridge.otherBridge() == L2Bridge); + assert(L1Bridge.messenger() == L1Messenger); + assertEq(L1Bridge.version(), "0.0.2"); } +} - function test_initialize() external { - assertEq( - address(L1Bridge.messenger()), - address(L1Messenger) - ); +contract L1StandardBridge_Initialize_Test is Bridge_Initializer { + function test_initialize_success() external { + assertEq(address(L1Bridge.messenger()), address(L1Messenger)); - assertEq( - address(L1Bridge.otherBridge()), - Predeploys.L2_STANDARD_BRIDGE - ); + assertEq(address(L1Bridge.otherBridge()), Predeploys.L2_STANDARD_BRIDGE); - assertEq( - address(L2Bridge), - Predeploys.L2_STANDARD_BRIDGE - ); + assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE); } +} + +contract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {} +contract L1StandardBridge_Receive_Test is Bridge_Initializer { // receive // - can accept ETH - function test_receive() external { + function test_receive_success() external { assertEq(address(op).balance, 0); vm.expectEmit(true, true, true, true); @@ -59,17 +57,21 @@ contract L1StandardBridge_Test is Bridge_Initializer { ); vm.prank(alice, alice); - (bool success,) = address(L1Bridge).call{ value: 100 }(hex""); + (bool success, ) = address(L1Bridge).call{ value: 100 }(hex""); assertEq(success, true); assertEq(address(op).balance, 100); } +} +contract L1StandardBridge_Receive_TestFail {} + +contract L1StandardBridge_DepositETH_Test is Bridge_Initializer { // depositETH // - emits ETHDepositInitiated // - calls optimismPortal.depositTransaction // - only EOA // - ETH ends up in the optimismPortal - function test_depositETH() external { + function test_depositETH_success() external { assertEq(address(op).balance, 0); vm.expectEmit(true, true, true, true); @@ -95,8 +97,10 @@ contract L1StandardBridge_Test is Bridge_Initializer { L1Bridge.depositETH{ value: 500 }(50000, hex"ff"); assertEq(address(op).balance, 500); } +} - function test_onlyEOADepositETH() external { +contract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer { + function test_DepositETH_revert_notEoa() external { // turn alice into a contract vm.etch(alice, address(L1Token).code); @@ -104,7 +108,9 @@ contract L1StandardBridge_Test is Bridge_Initializer { vm.prank(alice); L1Bridge.depositETH{ value: 1 }(300, hex""); } +} +contract L1StandardBridge_DepositETHTo_Test is Bridge_Initializer { // depositETHTo // - emits ETHDepositInitiated // - calls optimismPortal.depositTransaction @@ -122,12 +128,7 @@ contract L1StandardBridge_Test is Bridge_Initializer { // depositETHTo on the L1 bridge should be called vm.expectCall( address(L1Bridge), - abi.encodeWithSelector( - L1Bridge.depositETHTo.selector, - bob, - 1000, - hex"dead" - ) + abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 1000, hex"dead") ); // the L1 bridge should call @@ -155,22 +156,21 @@ contract L1StandardBridge_Test is Bridge_Initializer { vm.prank(alice, alice); L1Bridge.depositETHTo{ value: 600 }(bob, 1000, hex"dead"); } +} + +contract L1StandardBridge_DepositETHTo_TestFail is Bridge_Initializer {} + +contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer { + using stdStorage for StdStorage; // depositERC20 // - updates bridge.deposits // - emits ERC20DepositInitiated // - calls optimismPortal.depositTransaction // - only callable by EOA - function test_depositERC20() external { + function test_depositERC20_succeeds() external { vm.expectEmit(true, true, true, true); - emit ERC20DepositInitiated( - address(L1Token), - address(L2Token), - alice, - alice, - 100, - hex"" - ); + emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex""); deal(address(L1Token), alice, 100000, true); @@ -181,58 +181,38 @@ contract L1StandardBridge_Test is Bridge_Initializer { // to itself vm.expectCall( address(L1Token), - abi.encodeWithSelector( - ERC20.transferFrom.selector, - alice, - address(L1Bridge), - 100 - ) + abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100) ); // TODO: optimismPortal.depositTransaction call + event vm.prank(alice); - L1Bridge.depositERC20( - address(L1Token), - address(L2Token), - 100, - 10000, - hex"" - ); + L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex""); assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100); } +} - function test_onlyEOADepositERC20() external { +contract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer { + function test_depositERC20_revert_notEoa() external { // turn alice into a contract vm.etch(alice, hex"ffff"); vm.expectRevert("StandardBridge: function can only be called from an EOA"); vm.prank(alice, alice); - L1Bridge.depositERC20( - address(0), - address(0), - 100, - 100, - hex"" - ); + L1Bridge.depositERC20(address(0), address(0), 100, 100, hex""); } +} +contract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer { // depositERC20To // - updates bridge.deposits // - emits ERC20DepositInitiated // - calls optimismPortal.depositTransaction // - callable by a contract - function test_depositERC20To() external { + function test_depositERC20To_success() external { vm.expectEmit(true, true, true, true); - emit ERC20DepositInitiated( - address(L1Token), - address(L2Token), - alice, - bob, - 1000, - hex"" - ); + emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex""); deal(address(L1Token), alice, 100000, true); @@ -241,26 +221,18 @@ contract L1StandardBridge_Test is Bridge_Initializer { vm.expectCall( address(L1Token), - abi.encodeWithSelector( - ERC20.transferFrom.selector, - alice, - address(L1Bridge), - 1000 - ) + abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000) ); vm.prank(alice); - L1Bridge.depositERC20To( - address(L1Token), - address(L2Token), - bob, - 1000, - 10000, - hex"" - ); + L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex""); assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000); } +} + +contract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer { + using stdStorage for StdStorage; // finalizeETHWithdrawal // - emits ETHWithdrawalFinalized @@ -269,17 +241,9 @@ contract L1StandardBridge_Test is Bridge_Initializer { uint256 aliceBalance = alice.balance; vm.expectEmit(true, true, true, true); - emit ETHWithdrawalFinalized( - alice, - alice, - 100, - hex"" - ); + emit ETHWithdrawalFinalized(alice, alice, 100, hex""); - vm.expectCall( - alice, - hex"" - ); + vm.expectCall(alice, hex""); vm.mockCall( address(L1Bridge.messenger()), @@ -289,16 +253,17 @@ contract L1StandardBridge_Test is Bridge_Initializer { // ensure that the messenger has ETH to call with vm.deal(address(L1Bridge.messenger()), 100); vm.prank(address(L1Bridge.messenger())); - L1Bridge.finalizeETHWithdrawal{ value: 100 }( - alice, - alice, - 100, - hex"" - ); + L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex""); assertEq(address(L1Bridge.messenger()).balance, 0); assertEq(aliceBalance + 100, alice.balance); } +} + +contract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer {} + +contract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer { + using stdStorage for StdStorage; // finalizeERC20Withdrawal // - updates bridge.deposits @@ -319,22 +284,11 @@ contract L1StandardBridge_Test is Bridge_Initializer { assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100); vm.expectEmit(true, true, true, true); - emit ERC20WithdrawalFinalized( - address(L1Token), - address(L2Token), - alice, - alice, - 100, - hex"" - ); + emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex""); vm.expectCall( address(L1Token), - abi.encodeWithSelector( - ERC20.transfer.selector, - alice, - 100 - ) + abi.encodeWithSelector(ERC20.transfer.selector, alice, 100) ); vm.mockCall( @@ -355,8 +309,10 @@ contract L1StandardBridge_Test is Bridge_Initializer { assertEq(L1Token.balanceOf(address(L1Bridge)), 0); assertEq(L1Token.balanceOf(address(alice)), 100); } +} - function test_onlyPortalFinalizeERC20Withdrawal() external { +contract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer { + function test_finalizeERC20Withdrawal_revert_notMessenger() external { vm.mockCall( address(L1Bridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), @@ -374,7 +330,7 @@ contract L1StandardBridge_Test is Bridge_Initializer { ); } - function test_onlyL2BridgeFinalizeERC20Withdrawal() external { + function test_finalizeERC20Withdrawal_revert_notOtherBridge() external { vm.mockCall( address(L1Bridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), @@ -391,8 +347,16 @@ contract L1StandardBridge_Test is Bridge_Initializer { hex"" ); } +} - function test_finalizeBridgeETH_incorrectValueReverts() external { +// Todo: move these next two contracts into a test file specific to the direction agnostic +// StandardBridge interface +contract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer { + +} + +contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer { + function test_finalizeBridgeETH_revert_incorrectValue() external { address messenger = address(L1Bridge.messenger()); vm.mockCall( messenger, @@ -402,15 +366,10 @@ contract L1StandardBridge_Test is Bridge_Initializer { vm.deal(messenger, 100); vm.prank(messenger); vm.expectRevert("StandardBridge: amount sent does not match amount required"); - L1Bridge.finalizeBridgeETH{value: 50}( - alice, - alice, - 100, - hex"" - ); + L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex""); } - function test_finalizeBridgeETH_sendToSelfReverts() external { + function test_finalizeBridgeETH_revert_sendToSelf() external { address messenger = address(L1Bridge.messenger()); vm.mockCall( messenger, @@ -420,15 +379,10 @@ contract L1StandardBridge_Test is Bridge_Initializer { vm.deal(messenger, 100); vm.prank(messenger); vm.expectRevert("StandardBridge: cannot send to self"); - L1Bridge.finalizeBridgeETH{value: 100}( - alice, - address(L1Bridge), - 100, - hex"" - ); + L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex""); } - function test_finalizeBridgeETH_sendToMessengerReverts() external { + function test_finalizeBridgeETH_revert_sendToMessenger() external { address messenger = address(L1Bridge.messenger()); vm.mockCall( messenger, @@ -438,11 +392,6 @@ contract L1StandardBridge_Test is Bridge_Initializer { vm.deal(messenger, 100); vm.prank(messenger); vm.expectRevert("StandardBridge: cannot send to messenger"); - L1Bridge.finalizeBridgeETH{value: 100}( - alice, - messenger, - 100, - hex"" - ); + L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex""); } } diff --git a/packages/contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol index 2c3d7ea0adab3..f284195f256ce 100644 --- a/packages/contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol @@ -32,10 +32,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { function test_L2MessengerMessageVersion() external { (, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce()); - assertEq( - version, - L2Messenger.MESSAGE_VERSION() - ); + assertEq(version, L2Messenger.MESSAGE_VERSION()); } function test_L2MessengerSendMessage() external { @@ -56,9 +53,9 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ) ); - // WithdrawalInitiated event + // MessagePassed event vm.expectEmit(true, true, true, true); - emit WithdrawalInitiated( + emit MessagePassed( messagePasser.nonce(), address(L2Messenger), address(L1Messenger), @@ -83,10 +80,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { L2Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); L2Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); // the nonce increments for each message sent - assertEq( - nonce + 2, - L2Messenger.messageNonce() - ); + assertEq(nonce + 2, L2Messenger.messageNonce()); } function test_L2MessengerXDomainSenderReverts() external { @@ -101,7 +95,9 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { vm.prank(caller); - vm.expectRevert("CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade"); + vm.expectRevert( + "CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade" + ); L2Messenger.relayMessage( 0, // nonce sender, @@ -158,7 +154,14 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { vm.prank(caller); vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); - L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message); + L1Messenger.relayMessage( + Encoding.encodeVersionedNonce(0, 1), + sender, + target, + 0, + 0, + message + ); } // relayMessage: the xDomainMessageSender is reset to the original value @@ -168,7 +171,14 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); vm.prank(caller); - L2Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), address(0), address(0), 0, 0, hex""); + L2Messenger.relayMessage( + Encoding.encodeVersionedNonce(0, 1), + address(0), + address(0), + 0, + 0, + hex"" + ); vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); L2Messenger.xDomainMessageSender(); @@ -191,12 +201,19 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); uint256 value = 100; - bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, value, 0, hex"1111"); + bytes32 hash = Hashing.hashCrossDomainMessage( + Encoding.encodeVersionedNonce(0, 1), + sender, + target, + value, + 0, + hex"1111" + ); vm.etch(target, address(new Reverter()).code); vm.deal(address(caller), value); vm.prank(caller); - L2Messenger.relayMessage{value: value}( + L2Messenger.relayMessage{ value: value }( Encoding.encodeVersionedNonce(0, 1), // nonce sender, target, @@ -246,13 +263,23 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { hex"1111" ); - bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message); + bytes32 hash = Hashing.hashCrossDomainMessage( + Encoding.encodeVersionedNonce(0, 1), + sender, + target, + 0, + 0, + message + ); vm.etch(target, address(new CallerCaller()).code); vm.expectEmit(true, true, true, true, target); - emit WhatHappened(false, abi.encodeWithSignature("Error(string)", "ReentrancyGuard: reentrant call")); + emit WhatHappened( + false, + abi.encodeWithSignature("Error(string)", "ReentrancyGuard: reentrant call") + ); vm.prank(caller); vm.expectCall(target, message); diff --git a/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol b/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol index 787ec369a35f3..ae83d1f4ff610 100644 --- a/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol @@ -29,9 +29,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { } function testCannot_constructWithBadTimestamp() external { - vm.expectRevert( - "L2OutputOracle: starting L2 timestamp must be less than current time" - ); + vm.expectRevert("L2OutputOracle: starting L2 timestamp must be less than current time"); new L2OutputOracle( submissionInterval, @@ -78,7 +76,9 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq(proposal.timestamp, block.timestamp); // The block number is too low: - vm.expectRevert("L2OutputOracle: block number cannot be less than the starting block number."); + vm.expectRevert( + "L2OutputOracle: block number cannot be less than the starting block number." + ); oracle.getL2Output(0); // The block number is larger than the latest proposed output: @@ -292,9 +292,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { test_proposingAnotherOutput(); uint256 latestBlockNumber = oracle.latestBlockNumber(); - Types.OutputProposal memory proposalToDelete = oracle.getL2Output( - latestBlockNumber - ); + Types.OutputProposal memory proposalToDelete = oracle.getL2Output(latestBlockNumber); Types.OutputProposal memory newLatestOutput = oracle.getL2Output( latestBlockNumber - submissionInterval ); @@ -334,9 +332,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { test_proposingAnotherOutput(); uint256 previousBlockNumber = oracle.latestBlockNumber() - submissionInterval; - Types.OutputProposal memory proposalToDelete = oracle.getL2Output( - previousBlockNumber - ); + Types.OutputProposal memory proposalToDelete = oracle.getL2Output(previousBlockNumber); vm.prank(owner); vm.expectRevert( @@ -349,9 +345,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { test_proposingAnotherOutput(); uint256 latestBlockNumber = oracle.latestBlockNumber(); - Types.OutputProposal memory proposalToDelete = oracle.getL2Output( - latestBlockNumber - ); + Types.OutputProposal memory proposalToDelete = oracle.getL2Output(latestBlockNumber); // Modify the timestamp so that it does not match. proposalToDelete.timestamp -= 1; @@ -378,9 +372,7 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { assertEq(startingTimestamp, oracleImpl.STARTING_TIMESTAMP()); assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME()); - Types.OutputProposal memory initOutput = oracleImpl.getL2Output( - startingBlockNumber - ); + Types.OutputProposal memory initOutput = oracleImpl.getL2Output(startingBlockNumber); assertEq(genesisL2Output, initOutput.outputRoot); assertEq(initL1Time, initOutput.timestamp); @@ -392,7 +384,6 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { vm.expectRevert("Initializable: contract is already initialized"); L2OutputOracle(payable(proxy)).initialize( genesisL2Output, - startingBlockNumber, proposer, owner ); @@ -402,7 +393,6 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { vm.expectRevert("Initializable: contract is already initialized"); L2OutputOracle(oracleImpl).initialize( genesisL2Output, - startingBlockNumber, proposer, owner ); diff --git a/packages/contracts-bedrock/contracts/test/L2StandardBridge.t.sol b/packages/contracts-bedrock/contracts/test/L2StandardBridge.t.sol index 3d0bde0c57f47..675bac0384ec1 100644 --- a/packages/contracts-bedrock/contracts/test/L2StandardBridge.t.sol +++ b/packages/contracts-bedrock/contracts/test/L2StandardBridge.t.sol @@ -15,15 +15,9 @@ contract L2StandardBridge_Test is Bridge_Initializer { } function test_initialize() external { - assertEq( - address(L2Bridge.messenger()), - address(L2Messenger) - ); + assertEq(address(L2Bridge.messenger()), address(L2Messenger)); - assertEq( - address(L2Bridge.otherBridge()), - address(L1Bridge) - ); + assertEq(address(L2Bridge.otherBridge()), address(L1Bridge)); } // receive @@ -40,7 +34,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { // TODO: events from each contract vm.prank(alice, alice); - (bool success,) = address(L2Bridge).call{ value: 100 }(hex""); + (bool success, ) = address(L2Bridge).call{ value: 100 }(hex""); assertEq(success, true); assertEq(address(messagePasser).balance, 100); } @@ -52,12 +46,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { vm.expectRevert("StandardBridge: bridging ETH must include sufficient ETH value"); vm.prank(alice, alice); - L2Bridge.withdraw( - address(Predeploys.LEGACY_ERC20_ETH), - 100, - 1000, - hex"" - ); + L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex""); } // withdraw @@ -70,12 +59,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { assertEq(L2Token.balanceOf(alice), 100); vm.prank(alice, alice); - L2Bridge.withdraw( - address(L2Token), - 100, - 1000, - hex"" - ); + L2Bridge.withdraw(address(L2Token), 100, 1000, hex""); // TODO: events and calls @@ -87,12 +71,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { deal(address(L2Token), address(this), 100, true); vm.expectRevert("StandardBridge: function can only be called from an EOA"); - L2Bridge.withdraw( - address(L2Token), - 100, - 1000, - hex"" - ); + L2Bridge.withdraw(address(L2Token), 100, 1000, hex""); } // withdrawTo @@ -103,13 +82,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { deal(address(L2Token), alice, 100, true); vm.prank(alice, alice); - L2Bridge.withdrawTo( - address(L2Token), - bob, - 100, - 1000, - hex"" - ); + L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex""); // TODO: events and calls @@ -138,23 +111,9 @@ contract L2StandardBridge_Test is Bridge_Initializer { hex"" ); vm.expectEmit(true, true, true, true, address(L2Bridge)); - emit DepositFinalized( - address(L1Token), - address(L2Token), - alice, - alice, - 100, - hex"" - ); + emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex""); vm.prank(address(L2Messenger)); - L2Bridge.finalizeDeposit( - address(L1Token), - address(L2Token), - alice, - alice, - 100, - hex"" - ); + L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex""); } function test_finalizeBridgeETH_incorrectValueReverts() external { @@ -166,12 +125,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { vm.deal(address(L2Messenger), 100); vm.prank(address(L2Messenger)); vm.expectRevert("StandardBridge: amount sent does not match amount required"); - L2Bridge.finalizeBridgeETH{value: 50}( - alice, - alice, - 100, - hex"" - ); + L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex""); } function test_finalizeBridgeETH_sendToSelfReverts() external { @@ -183,12 +137,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { vm.deal(address(L2Messenger), 100); vm.prank(address(L2Messenger)); vm.expectRevert("StandardBridge: cannot send to self"); - L2Bridge.finalizeBridgeETH{value: 100}( - alice, - address(L2Bridge), - 100, - hex"" - ); + L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex""); } function test_finalizeBridgeETH_sendToMessengerReverts() external { @@ -200,11 +149,6 @@ contract L2StandardBridge_Test is Bridge_Initializer { vm.deal(address(L2Messenger), 100); vm.prank(address(L2Messenger)); vm.expectRevert("StandardBridge: cannot send to messenger"); - L2Bridge.finalizeBridgeETH{value: 100}( - alice, - address(L2Messenger), - 100, - hex"" - ); + L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex""); } } diff --git a/packages/contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol b/packages/contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol index 6bd21e3c75176..1837d98d9ad52 100644 --- a/packages/contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol +++ b/packages/contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol @@ -9,7 +9,7 @@ import { Hashing } from "../libraries/Hashing.sol"; contract L2ToL1MessagePasserTest is CommonTest { L2ToL1MessagePasser messagePasser; - event WithdrawalInitiated( + event MessagePassed( uint256 indexed nonce, address indexed sender, address indexed target, @@ -18,11 +18,11 @@ contract L2ToL1MessagePasserTest is CommonTest { bytes data ); - event WithdrawalInitiatedExtension1(bytes32 indexed hash); + event MessagePassedExtension1(bytes32 indexed hash); event WithdrawerBalanceBurnt(uint256 indexed amount); - function setUp() virtual public { + function setUp() public virtual { messagePasser = new L2ToL1MessagePasser(); } @@ -36,14 +36,7 @@ contract L2ToL1MessagePasserTest is CommonTest { uint256 nonce = messagePasser.nonce(); vm.expectEmit(true, true, true, true); - emit WithdrawalInitiated( - nonce, - _sender, - _target, - _value, - _gasLimit, - _data - ); + emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data); bytes32 withdrawalHash = Hashing.hashWithdrawal( Types.WithdrawalTransaction({ @@ -57,43 +50,23 @@ contract L2ToL1MessagePasserTest is CommonTest { ); vm.expectEmit(true, true, true, true); - emit WithdrawalInitiatedExtension1(withdrawalHash); + emit MessagePassedExtension1(withdrawalHash); vm.deal(_sender, _value); vm.prank(_sender); - messagePasser.initiateWithdrawal{ value: _value }( - _target, - _gasLimit, - _data - ); + messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data); - assertEq( - messagePasser.sentMessages(withdrawalHash), - true - ); + assertEq(messagePasser.sentMessages(withdrawalHash), true); - bytes32 slot = keccak256(bytes.concat( - withdrawalHash, - bytes32(0) - )); + bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0))); - assertEq( - vm.load(address(messagePasser), slot), - bytes32(uint256(1)) - ); + assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1))); } // Test: initiateWithdrawal should emit the correct log when called by a contract function test_initiateWithdrawal_fromContract() external { vm.expectEmit(true, true, true, true); - emit WithdrawalInitiated( - messagePasser.nonce(), - address(this), - address(4), - 100, - 64000, - hex"" - ); + emit MessagePassed(messagePasser.nonce(), address(this), address(4), 100, 64000, hex""); bytes32 withdrawalHash = Hashing.hashWithdrawal( Types.WithdrawalTransaction( @@ -107,14 +80,10 @@ contract L2ToL1MessagePasserTest is CommonTest { ); vm.expectEmit(true, true, true, true); - emit WithdrawalInitiatedExtension1(withdrawalHash); + emit MessagePassedExtension1(withdrawalHash); vm.deal(address(this), 2**64); - messagePasser.initiateWithdrawal{ value: 100 }( - address(4), - 64000, - hex"" - ); + messagePasser.initiateWithdrawal{ value: 100 }(address(4), 64000, hex""); } // Test: initiateWithdrawal should emit the correct log when called by an EOA @@ -129,31 +98,13 @@ contract L2ToL1MessagePasserTest is CommonTest { vm.prank(alice, alice); vm.deal(alice, 2**64); vm.expectEmit(true, true, true, true); - emit WithdrawalInitiated( - nonce, - alice, - target, - value, - gasLimit, - data - ); + emit MessagePassed(nonce, alice, target, value, gasLimit, data); bytes32 withdrawalHash = Hashing.hashWithdrawal( - Types.WithdrawalTransaction( - nonce, - alice, - target, - value, - gasLimit, - data - ) + Types.WithdrawalTransaction(nonce, alice, target, value, gasLimit, data) ); - messagePasser.initiateWithdrawal{ value: value }( - target, - gasLimit, - data - ); + messagePasser.initiateWithdrawal{ value: value }(target, gasLimit, data); // the sent messages mapping is filled assertEq(messagePasser.sentMessages(withdrawalHash), true); diff --git a/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol b/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol index ad02dc9ecebed..5b3f3eeb7c90f 100644 --- a/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol +++ b/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol @@ -77,7 +77,10 @@ contract OptimismMintableERC20_Test is Bridge_Initializer { assertEq(iface2, type(ILegacyMintableERC20).interfaceId); assert(L2Token.supportsInterface(iface2)); - bytes4 iface3 = L2Token.remoteToken.selector ^ L2Token.bridge.selector ^ L2Token.mint.selector ^ L2Token.burn.selector; + bytes4 iface3 = L2Token.remoteToken.selector ^ + L2Token.bridge.selector ^ + L2Token.mint.selector ^ + L2Token.burn.selector; assertEq(iface3, type(IOptimismMintableERC20).interfaceId); assert(L2Token.supportsInterface(iface3)); } diff --git a/packages/contracts-bedrock/contracts/test/OptimismMintableERC20Factory.t.sol b/packages/contracts-bedrock/contracts/test/OptimismMintableERC20Factory.t.sol index 0e4d16a8782d4..fc2babe0f6e61 100644 --- a/packages/contracts-bedrock/contracts/test/OptimismMintableERC20Factory.t.sol +++ b/packages/contracts-bedrock/contracts/test/OptimismMintableERC20Factory.t.sol @@ -25,17 +25,10 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer { address local = LibRLP.computeAddress(address(L2TokenFactory), 2); vm.expectEmit(true, true, true, true); - emit StandardL2TokenCreated( - remote, - local - ); + emit StandardL2TokenCreated(remote, local); vm.expectEmit(true, true, true, true); - emit OptimismMintableERC20Created( - local, - remote, - alice - ); + emit OptimismMintableERC20Created(local, remote, alice); vm.prank(alice); L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); @@ -50,17 +43,10 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer { address local = LibRLP.computeAddress(address(L2TokenFactory), 3); vm.expectEmit(true, true, true, true); - emit StandardL2TokenCreated( - remote, - local - ); + emit StandardL2TokenCreated(remote, local); vm.expectEmit(true, true, true, true); - emit OptimismMintableERC20Created( - local, - remote, - alice - ); + emit OptimismMintableERC20Created(local, remote, alice); vm.prank(alice); L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); diff --git a/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol b/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol index a1f79e6aa997f..2a88b8945d42c 100644 --- a/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol @@ -422,13 +422,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { gasLimit: gasLimit, data: hex"" }); - ( - bytes32 stateRoot, - bytes32 storageRoot, - , - , - bytes memory withdrawalProof - ) = ffi.getFinalizeWithdrawalTransactionInputs(insufficientGasTx); + (bytes32 stateRoot, bytes32 storageRoot, , , bytes memory withdrawalProof) = ffi + .getFinalizeWithdrawalTransactionInputs(insufficientGasTx); Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({ version: bytes32(0), stateRoot: stateRoot, diff --git a/packages/contracts-bedrock/contracts/test/Proxy.t.sol b/packages/contracts-bedrock/contracts/test/Proxy.t.sol index 4b72bf957253f..bb96e53bd113a 100644 --- a/packages/contracts-bedrock/contracts/test/Proxy.t.sol +++ b/packages/contracts-bedrock/contracts/test/Proxy.t.sol @@ -30,10 +30,9 @@ contract Proxy_Test is Test { address alice = address(64); bytes32 internal constant IMPLEMENTATION_KEY = - bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1); - bytes32 internal constant OWNER_KEY = - bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1); + bytes32 internal constant OWNER_KEY = bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1); Proxy proxy; SimpleStorage simpleStorage; @@ -54,10 +53,7 @@ contract Proxy_Test is Test { proxy.upgradeTo(address(6)); bytes32 key = vm.load(address(proxy), IMPLEMENTATION_KEY); - assertEq( - address(6), - Bytes32AddressLib.fromLast20Bytes(key) - ); + assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key)); vm.prank(alice); address impl = proxy.implementation(); @@ -70,10 +66,7 @@ contract Proxy_Test is Test { proxy.changeAdmin(address(6)); bytes32 key = vm.load(address(proxy), OWNER_KEY); - assertEq( - address(6), - Bytes32AddressLib.fromLast20Bytes(key) - ); + assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key)); vm.prank(address(6)); address owner = proxy.admin(); @@ -186,10 +179,7 @@ contract Proxy_Test is Test { // match a function on the implementation. vm.expectRevert("Proxy: delegatecall to new implementation contract failed"); vm.prank(alice); - proxy.upgradeToAndCall( - address(simpleStorage), - hex"" - ); + proxy.upgradeToAndCall(address(simpleStorage), hex""); // The implementation address should have not // updated because the call to `upgradeToAndCall` diff --git a/packages/contracts-bedrock/contracts/test/ProxyAdmin.t.sol b/packages/contracts-bedrock/contracts/test/ProxyAdmin.t.sol index f061cded10ef6..52de023ca2514 100644 --- a/packages/contracts-bedrock/contracts/test/ProxyAdmin.t.sol +++ b/packages/contracts-bedrock/contracts/test/ProxyAdmin.t.sol @@ -62,10 +62,7 @@ contract ProxyAdmin_Test is Test { function test_setImplementationName() external { vm.prank(alice); admin.setImplementationName(address(1), "foo"); - assertEq( - admin.implementationName(address(1)), - "foo" - ); + assertEq(admin.implementationName(address(1)), "foo"); } function test_onlyOwnerSetAddressManager() external { @@ -88,10 +85,7 @@ contract ProxyAdmin_Test is Test { } function test_proxyType() external { - assertEq( - uint256(admin.proxyType(address(proxy))), - uint256(ProxyAdmin.ProxyType.ERC1967) - ); + assertEq(uint256(admin.proxyType(address(proxy))), uint256(ProxyAdmin.ProxyType.ERC1967)); assertEq( uint256(admin.proxyType(address(chugsplash))), uint256(ProxyAdmin.ProxyType.CHUGSPLASH) @@ -186,15 +180,9 @@ contract ProxyAdmin_Test is Test { if (proxyType == ProxyAdmin.ProxyType.ERC1967) { assertEq(Proxy(payable(_proxy)).admin(), address(128)); } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) { - assertEq( - L1ChugSplashProxy(payable(_proxy)).getOwner(), - address(128) - ); + assertEq(L1ChugSplashProxy(payable(_proxy)).getOwner(), address(128)); } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) { - assertEq( - addressManager.owner(), - address(128) - ); + assertEq(addressManager.owner(), address(128)); } else { assert(false); } diff --git a/packages/contracts-bedrock/contracts/test/RLP.t.sol b/packages/contracts-bedrock/contracts/test/RLP.t.sol index c07039c60de54..cae4a45fa454b 100644 --- a/packages/contracts-bedrock/contracts/test/RLP.t.sol +++ b/packages/contracts-bedrock/contracts/test/RLP.t.sol @@ -13,19 +13,58 @@ library LibRLP { function computeAddress(address deployer, uint256 nonce) internal pure returns (address) { // The integer zero is treated as an empty byte string, and as a result it only has a length prefix, 0x80, computed via 0x80 + 0. // A one byte integer uses its own value as its length prefix, there is no additional "0x80 + length" prefix that comes before it. - if (nonce == 0x00) return keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))).fromLast20Bytes(); - if (nonce <= 0x7f) return keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))).fromLast20Bytes(); + if (nonce == 0x00) + return + keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))) + .fromLast20Bytes(); + if (nonce <= 0x7f) + return + keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))) + .fromLast20Bytes(); // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length. - if (nonce <= type(uint8).max) return keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))).fromLast20Bytes(); - if (nonce <= type(uint16).max) return keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))).fromLast20Bytes(); - if (nonce <= type(uint24).max) return keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))).fromLast20Bytes(); + if (nonce <= type(uint8).max) + return + keccak256( + abi.encodePacked( + bytes1(0xd7), + bytes1(0x94), + deployer, + bytes1(0x81), + uint8(nonce) + ) + ).fromLast20Bytes(); + if (nonce <= type(uint16).max) + return + keccak256( + abi.encodePacked( + bytes1(0xd8), + bytes1(0x94), + deployer, + bytes1(0x82), + uint16(nonce) + ) + ).fromLast20Bytes(); + if (nonce <= type(uint24).max) + return + keccak256( + abi.encodePacked( + bytes1(0xd9), + bytes1(0x94), + deployer, + bytes1(0x83), + uint24(nonce) + ) + ).fromLast20Bytes(); // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce) // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex) // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex) // We assume nobody can have a nonce large enough to require more than 32 bytes. - return keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))).fromLast20Bytes(); + return + keccak256( + abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)) + ).fromLast20Bytes(); } } diff --git a/packages/contracts-bedrock/contracts/test/RLPReader.t.sol b/packages/contracts-bedrock/contracts/test/RLPReader.t.sol index c24f1b19be91a..c3a3644e9e77a 100644 --- a/packages/contracts-bedrock/contracts/test/RLPReader.t.sol +++ b/packages/contracts-bedrock/contracts/test/RLPReader.t.sol @@ -6,15 +6,9 @@ import { CommonTest } from "./CommonTest.t.sol"; contract RLPReader_Test is CommonTest { function testReadBool() external { - assertEq( - RLPReader.readBool(hex"01"), - true - ); + assertEq(RLPReader.readBool(hex"01"), true); - assertEq( - RLPReader.readBool(hex"00"), - false - ); + assertEq(RLPReader.readBool(hex"00"), false); } function test_readBoolInvalidValue() external { @@ -35,10 +29,7 @@ contract RLPReader_Test is CommonTest { } function test_readAddressSmall() external { - assertEq( - RLPReader.readAddress(hex"12"), - address(0) - ); + assertEq(RLPReader.readAddress(hex"12"), address(0)); } function test_readAddressTooLarge() external { @@ -52,24 +43,15 @@ contract RLPReader_Test is CommonTest { } function test_readBytes_bytestring00() external { - assertEq( - RLPReader.readBytes(hex"00"), - hex"00" - ); + assertEq(RLPReader.readBytes(hex"00"), hex"00"); } function test_readBytes_bytestring01() external { - assertEq( - RLPReader.readBytes(hex"01"), - hex"01" - ); + assertEq(RLPReader.readBytes(hex"01"), hex"01"); } function test_readBytes_bytestring7f() external { - assertEq( - RLPReader.readBytes(hex"7f"), - hex"7f" - ); + assertEq(RLPReader.readBytes(hex"7f"), hex"7f"); } function test_readBytes_revertListItem() external { @@ -94,98 +76,76 @@ contract RLPReader_Test is CommonTest { function test_readBytes32_revertOnTooLong() external { vm.expectRevert("RLPReader: invalid RLP bytes32 value"); - RLPReader.readBytes32(hex"11110000000000000000000000000000000000000000000000000000000000000000"); + RLPReader.readBytes32( + hex"11110000000000000000000000000000000000000000000000000000000000000000" + ); } function test_readString_emptyString() external { - assertEq( - RLPReader.readString(hex"80"), - hex"" - ); + assertEq(RLPReader.readString(hex"80"), hex""); } function test_readString_shortString() external { - assertEq( - RLPReader.readString(hex"83646f67"), - "dog" - ); + assertEq(RLPReader.readString(hex"83646f67"), "dog"); } function test_readString_shortString2() external { assertEq( - RLPReader.readString(hex"b74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69"), + RLPReader.readString( + hex"b74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69" + ), "Lorem ipsum dolor sit amet, consectetur adipisicing eli" ); } function test_readString_longString() external { assertEq( - RLPReader.readString(hex"b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974"), + RLPReader.readString( + hex"b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974" + ), "Lorem ipsum dolor sit amet, consectetur adipisicing elit" ); } function test_readString_longString2() external { assertEq( - RLPReader.readString(hex"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174"), + RLPReader.readString( + hex"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174" + ), "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique eu, ultrices at risus. Morbi a est imperdiet mi ullamcorper aliquet suscipit nec lorem. Aenean quis leo mollis, vulputate elit varius, consequat enim. Nulla ultrices turpis justo, et posuere urna consectetur nec. Proin non convallis metus. Donec tempor ipsum in mauris congue sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse convallis sem vel massa faucibus, eget lacinia lacus tempor. Nulla quis ultricies purus. Proin auctor rhoncus nibh condimentum mollis. Aliquam consequat enim at metus luctus, a eleifend purus egestas. Curabitur at nibh metus. Nam bibendum, neque at auctor tristique, lorem libero aliquet arcu, non interdum tellus lectus sit amet eros. Cras rhoncus, metus ac ornare cursus, dolor justo ultrices metus, at ullamcorper volutpat" ); } function test_readUint256_zero() external { - assertEq( - RLPReader.readUint256(hex"80"), - 0 - ); + assertEq(RLPReader.readUint256(hex"80"), 0); } function test_readUint256_smallInt() external { - assertEq( - RLPReader.readUint256(hex"01"), - 1 - ); + assertEq(RLPReader.readUint256(hex"01"), 1); } function test_readUint256_smallInt2() external { - assertEq( - RLPReader.readUint256(hex"10"), - 16 - ); + assertEq(RLPReader.readUint256(hex"10"), 16); } function test_readUint256_smallInt3() external { - assertEq( - RLPReader.readUint256(hex"4f"), - 79 - ); + assertEq(RLPReader.readUint256(hex"4f"), 79); } function test_readUint256_smallInt4() external { - assertEq( - RLPReader.readUint256(hex"7f"), - 127 - ); + assertEq(RLPReader.readUint256(hex"7f"), 127); } function test_readUint256_mediumInt1() external { - assertEq( - RLPReader.readUint256(hex"8180"), - 128 - ); + assertEq(RLPReader.readUint256(hex"8180"), 128); } function test_readUint256_mediumInt2() external { - assertEq( - RLPReader.readUint256(hex"8203e8"), - 1000 - ); + assertEq(RLPReader.readUint256(hex"8203e8"), 1000); } function test_readUint256_mediumInt3() external { - assertEq( - RLPReader.readUint256(hex"830186a0"), - 100000 - ); + assertEq(RLPReader.readUint256(hex"830186a0"), 100000); } function test_readList_empty() external { @@ -211,7 +171,9 @@ contract RLPReader_Test is CommonTest { } function test_readList_shortListMax1() external { - RLPReader.RLPItem[] memory list = RLPReader.readList(hex"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572"); + RLPReader.RLPItem[] memory list = RLPReader.readList( + hex"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572" + ); assertEq(list.length, 11); assertEq(RLPReader.readRawBytes(list[0]), hex"8461736466"); @@ -228,7 +190,9 @@ contract RLPReader_Test is CommonTest { } function test_readList_longList1() external { - RLPReader.RLPItem[] memory list = RLPReader.readList(hex"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376"); + RLPReader.RLPItem[] memory list = RLPReader.readList( + hex"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376" + ); assertEq(list.length, 4); assertEq(RLPReader.readRawBytes(list[0]), hex"cf84617364668471776572847a786376"); @@ -238,7 +202,9 @@ contract RLPReader_Test is CommonTest { } function test_readList_longList2() external { - RLPReader.RLPItem[] memory list = RLPReader.readList(hex"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376"); + RLPReader.RLPItem[] memory list = RLPReader.readList( + hex"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376" + ); assertEq(list.length, 32); for (uint256 i = 0; i < 32; i++) { @@ -263,7 +229,9 @@ contract RLPReader_Test is CommonTest { } function test_readList_dictTest1() external { - RLPReader.RLPItem[] memory list = RLPReader.readList(hex"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34"); + RLPReader.RLPItem[] memory list = RLPReader.readList( + hex"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34" + ); assertEq(list.length, 4); assertEq(RLPReader.readRawBytes(list[0]), hex"ca846b6579318476616c31"); @@ -284,7 +252,9 @@ contract RLPReader_Test is CommonTest { function test_readList_notLongEnough() external { vm.expectRevert("RLPReader: invalid RLP short list"); - RLPReader.readList(hex"efdebdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + RLPReader.readList( + hex"efdebdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + ); } function test_readList_int32Overflow() external { @@ -299,12 +269,16 @@ contract RLPReader_Test is CommonTest { function test_readList_incorrectLengthInArray() external { vm.expectRevert("RLPReader: invalid RLP list value"); - RLPReader.readList(hex"b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0"); + RLPReader.readList( + hex"b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0" + ); } function test_readList_leadingZerosInLongLengthArray1() external { vm.expectRevert("RLPReader: invalid RLP list value"); - RLPReader.readList(hex"b90040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"); + RLPReader.readList( + hex"b90040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + ); } function test_readList_leadingZerosInLongLengthArray2() external { @@ -314,7 +288,9 @@ contract RLPReader_Test is CommonTest { function test_readList_leadingZerosInLongLengthList1() external { vm.expectRevert("RLPReader: provided RLP list exceeds max list length"); - RLPReader.readList(hex"fb00000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"); + RLPReader.readList( + hex"fb00000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + ); } function test_readList_nonOptimalLongLengthArray1() external { diff --git a/packages/contracts-bedrock/contracts/test/RLPWriter.t.sol b/packages/contracts-bedrock/contracts/test/RLPWriter.t.sol index 426af74b72b71..311e8f5db0234 100644 --- a/packages/contracts-bedrock/contracts/test/RLPWriter.t.sol +++ b/packages/contracts-bedrock/contracts/test/RLPWriter.t.sol @@ -6,38 +6,23 @@ import { CommonTest } from "./CommonTest.t.sol"; contract RLPWriter_Test is CommonTest { function test_writeString_empty() external { - assertEq( - RLPWriter.writeString(""), - hex"80" - ); + assertEq(RLPWriter.writeString(""), hex"80"); } function test_writeString_bytestring00() external { - assertEq( - RLPWriter.writeString("\u0000"), - hex"00" - ); + assertEq(RLPWriter.writeString("\u0000"), hex"00"); } function test_writeString_bytestring01() external { - assertEq( - RLPWriter.writeString("\u0001"), - hex"01" - ); + assertEq(RLPWriter.writeString("\u0001"), hex"01"); } function test_writeString_bytestring7f() external { - assertEq( - RLPWriter.writeString("\u007F"), - hex"7f" - ); + assertEq(RLPWriter.writeString("\u007F"), hex"7f"); } function test_writeString_shortstring() external { - assertEq( - RLPWriter.writeString("dog"), - hex"83646f67" - ); + assertEq(RLPWriter.writeString("dog"), hex"83646f67"); } function test_writeString_shortstring2() external { @@ -56,72 +41,47 @@ contract RLPWriter_Test is CommonTest { function test_writeString_longstring2() external { assertEq( - RLPWriter.writeString("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique eu, ultrices at risus. Morbi a est imperdiet mi ullamcorper aliquet suscipit nec lorem. Aenean quis leo mollis, vulputate elit varius, consequat enim. Nulla ultrices turpis justo, et posuere urna consectetur nec. Proin non convallis metus. Donec tempor ipsum in mauris congue sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse convallis sem vel massa faucibus, eget lacinia lacus tempor. Nulla quis ultricies purus. Proin auctor rhoncus nibh condimentum mollis. Aliquam consequat enim at metus luctus, a eleifend purus egestas. Curabitur at nibh metus. Nam bibendum, neque at auctor tristique, lorem libero aliquet arcu, non interdum tellus lectus sit amet eros. Cras rhoncus, metus ac ornare cursus, dolor justo ultrices metus, at ullamcorper volutpat"), + RLPWriter.writeString( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique eu, ultrices at risus. Morbi a est imperdiet mi ullamcorper aliquet suscipit nec lorem. Aenean quis leo mollis, vulputate elit varius, consequat enim. Nulla ultrices turpis justo, et posuere urna consectetur nec. Proin non convallis metus. Donec tempor ipsum in mauris congue sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse convallis sem vel massa faucibus, eget lacinia lacus tempor. Nulla quis ultricies purus. Proin auctor rhoncus nibh condimentum mollis. Aliquam consequat enim at metus luctus, a eleifend purus egestas. Curabitur at nibh metus. Nam bibendum, neque at auctor tristique, lorem libero aliquet arcu, non interdum tellus lectus sit amet eros. Cras rhoncus, metus ac ornare cursus, dolor justo ultrices metus, at ullamcorper volutpat" + ), hex"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174" ); } function test_writeUint_zero() external { - assertEq( - RLPWriter.writeUint(0x0), - hex"80" - ); + assertEq(RLPWriter.writeUint(0x0), hex"80"); } function test_writeUint_smallint() external { - assertEq( - RLPWriter.writeUint(1), - hex"01" - ); + assertEq(RLPWriter.writeUint(1), hex"01"); } function test_writeUint_smallint2() external { - assertEq( - RLPWriter.writeUint(16), - hex"10" - ); + assertEq(RLPWriter.writeUint(16), hex"10"); } function test_writeUint_smallint3() external { - assertEq( - RLPWriter.writeUint(79), - hex"4f" - ); + assertEq(RLPWriter.writeUint(79), hex"4f"); } function test_writeUint_smallint4() external { - assertEq( - RLPWriter.writeUint(127), - hex"7f" - ); + assertEq(RLPWriter.writeUint(127), hex"7f"); } function test_writeUint_mediumint() external { - assertEq( - RLPWriter.writeUint(128), - hex"8180" - ); + assertEq(RLPWriter.writeUint(128), hex"8180"); } function test_writeUint_mediumint2() external { - assertEq( - RLPWriter.writeUint(1000), - hex"8203e8" - ); + assertEq(RLPWriter.writeUint(1000), hex"8203e8"); } function test_writeUint_mediumint3() external { - assertEq( - RLPWriter.writeUint(100000), - hex"830186a0" - ); + assertEq(RLPWriter.writeUint(100000), hex"830186a0"); } function test_writeList_empty() external { - assertEq( - RLPWriter.writeList(new bytes[](0)), - hex"c0" - ); + assertEq(RLPWriter.writeList(new bytes[](0)), hex"c0"); } function test_writeList_stringList() external { @@ -130,10 +90,7 @@ contract RLPWriter_Test is CommonTest { list[1] = RLPWriter.writeString("god"); list[2] = RLPWriter.writeString("cat"); - assertEq( - RLPWriter.writeList(list), - hex"cc83646f6783676f6483636174" - ); + assertEq(RLPWriter.writeList(list), hex"cc83646f6783676f6483636174"); } function test_writeList_multiList() external { @@ -145,10 +102,7 @@ contract RLPWriter_Test is CommonTest { list[1] = RLPWriter.writeList(list2); list[2] = RLPWriter.writeUint(1); - assertEq( - RLPWriter.writeList(list), - hex"c6827a77c10401" - ); + assertEq(RLPWriter.writeList(list), hex"c6827a77c10401"); } function test_writeList_shortListMax1() external { @@ -208,7 +162,6 @@ contract RLPWriter_Test is CommonTest { ); } - function test_writeList_listoflists() external { // [ [ [], [] ], [] ] bytes[] memory list = new bytes[](2); @@ -220,10 +173,7 @@ contract RLPWriter_Test is CommonTest { list[0] = RLPWriter.writeList(list2); list[1] = RLPWriter.writeList(new bytes[](0)); - assertEq( - RLPWriter.writeList(list), - hex"c4c2c0c0c0" - ); + assertEq(RLPWriter.writeList(list), hex"c4c2c0c0c0"); } function test_writeList_listoflists2() external { @@ -242,10 +192,7 @@ contract RLPWriter_Test is CommonTest { list[2] = RLPWriter.writeList(list3); - assertEq( - RLPWriter.writeList(list), - hex"c7c0c1c0c3c0c1c0" - ); + assertEq(RLPWriter.writeList(list), hex"c7c0c1c0c3c0c1c0"); } function test_writeList_dictTest1() external { diff --git a/packages/contracts-bedrock/contracts/test/ResourceMetering.t.sol b/packages/contracts-bedrock/contracts/test/ResourceMetering.t.sol index 1c3bcf5bb3228..3b51683c52918 100644 --- a/packages/contracts-bedrock/contracts/test/ResourceMetering.t.sol +++ b/packages/contracts-bedrock/contracts/test/ResourceMetering.t.sol @@ -97,7 +97,7 @@ contract ResourceMetering_Test is CommonTest { vm.roll(initialBlockNum + 1); meter.use(0); - (uint128 postBaseFee,,) = meter.params(); + (uint128 postBaseFee, , ) = meter.params(); // Base fee increases by 1/8 the difference assertEq(postBaseFee, 1375000000); } diff --git a/packages/contracts-bedrock/contracts/test/SafeCall.t.sol b/packages/contracts-bedrock/contracts/test/SafeCall.t.sol index 28b1d5613e5fc..8373bcbad6159 100644 --- a/packages/contracts-bedrock/contracts/test/SafeCall.t.sol +++ b/packages/contracts-bedrock/contracts/test/SafeCall.t.sol @@ -20,13 +20,9 @@ contract SafeCall_Test is CommonTest { vm.assume(to != address(vm)); vm.assume(from != address(vm)); // don't call the console - vm.assume( - to != address(0x000000000000000000636F6e736F6c652e6c6f67) - ); + vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67)); // don't call the create2 deployer - vm.assume( - to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C) - ); + vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C)); // don't send funds to self vm.assume(from != to); @@ -34,19 +30,10 @@ contract SafeCall_Test is CommonTest { vm.deal(from, value); assertEq(from.balance, value, "from balance not dealt"); - vm.expectCall( - to, - value, - data - ); + vm.expectCall(to, value, data); vm.prank(from); - bool success = SafeCall.call( - to, - gas, - value, - data - ); + bool success = SafeCall.call(to, gas, value, data); assertEq(success, true, "call not successful"); assertEq(to.balance, value, "to balance received"); diff --git a/packages/contracts-bedrock/contracts/test/Semver.t.sol b/packages/contracts-bedrock/contracts/test/Semver.t.sol index c2042a89a9c2c..25f729211fe5d 100644 --- a/packages/contracts-bedrock/contracts/test/Semver.t.sol +++ b/packages/contracts-bedrock/contracts/test/Semver.t.sol @@ -27,10 +27,7 @@ contract Semver_Test is CommonTest { * @notice Test the version getter */ function test_version() external { - assertEq( - semver.version(), - "7.8.0" - ); + assertEq(semver.version(), "7.8.0"); } /** @@ -43,9 +40,6 @@ contract Semver_Test is CommonTest { vm.prank(alice); proxy.upgradeTo(address(semver)); - assertEq( - Semver(address(proxy)).version(), - "7.8.0" - ); + assertEq(Semver(address(proxy)).version(), "7.8.0"); } } diff --git a/packages/contracts-bedrock/contracts/test/SequencerFeeVault.t.sol b/packages/contracts-bedrock/contracts/test/SequencerFeeVault.t.sol index 0687ea56200c3..39f308e99047e 100644 --- a/packages/contracts-bedrock/contracts/test/SequencerFeeVault.t.sol +++ b/packages/contracts-bedrock/contracts/test/SequencerFeeVault.t.sol @@ -8,17 +8,13 @@ import { L2StandardBridge } from "../L2/L2StandardBridge.sol"; import { Predeploys } from "../libraries/Predeploys.sol"; contract SequencerFeeVault_Test is Bridge_Initializer { - SequencerFeeVault vault = - SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET)); + SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET)); address constant recipient = address(256); function setUp() public override { super.setUp(); - vm.etch( - Predeploys.SEQUENCER_FEE_WALLET, - address(new SequencerFeeVault()).code - ); + vm.etch(Predeploys.SEQUENCER_FEE_WALLET, address(new SequencerFeeVault()).code); vm.store( Predeploys.SEQUENCER_FEE_WALLET, @@ -28,33 +24,21 @@ contract SequencerFeeVault_Test is Bridge_Initializer { } function test_minWithdrawalAmount() external { - assertEq( - vault.MIN_WITHDRAWAL_AMOUNT(), - 15 ether - ); + assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), 15 ether); } function test_constructor() external { - assertEq( - vault.l1FeeWallet(), - recipient - ); + assertEq(vault.l1FeeWallet(), recipient); } function test_receive() external { - assertEq( - address(vault).balance, - 0 - ); + assertEq(address(vault).balance, 0); vm.prank(alice); - (bool success,) = address(vault).call{ value: 100 }(hex""); + (bool success, ) = address(vault).call{ value: 100 }(hex""); assertEq(success, true); - assertEq( - address(vault).balance, - 100 - ); + assertEq(address(vault).balance, 100); } function test_revertWithdraw() external { diff --git a/packages/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol b/packages/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol index 8ddfb725ce249..983392401b369 100644 --- a/packages/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol @@ -53,22 +53,22 @@ abstract contract CrossDomainMessenger is /** * @notice Constant overhead added to the base gas for a message. */ - uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000; + uint64 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000; /** * @notice Numerator for dynamic overhead added to the base gas for a message. */ - uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016; + uint64 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016; /** * @notice Denominator for dynamic overhead added to the base gas for a message. */ - uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000; + uint64 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000; /** * @notice Extra gas added to base gas for each byte of calldata in a message. */ - uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16; + uint64 public constant MIN_GAS_CALLDATA_OVERHEAD = 16; /** * @notice Minimum amount of gas required to relay a message. @@ -369,13 +369,16 @@ abstract contract CrossDomainMessenger is * * @return Amount of gas required to guarantee message receipt. */ - function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) { + function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint64) { + // We peform the following math on uint64s to avoid overflow errors. Multiplying the + // by MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR would otherwise limit the _mingasLimit to + // approximately 4.2 MM. return // Dynamic overhead - ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) / + ((uint64(_minGasLimit) * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) / MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) + // Calldata overhead - (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) + + (uint64(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) + // Constant overhead MIN_GAS_CONSTANT_OVERHEAD; } diff --git a/packages/contracts-bedrock/deploy/001-InitImplementations.deploy.ts b/packages/contracts-bedrock/deploy/001-InitImplementations.deploy.ts index 9d339f103e924..7d1fc1b43dc2c 100644 --- a/packages/contracts-bedrock/deploy/001-InitImplementations.deploy.ts +++ b/packages/contracts-bedrock/deploy/001-InitImplementations.deploy.ts @@ -10,7 +10,6 @@ const upgradeABIs = { 'initialize(bytes32,uint256,address,address)', [ deployConfig.l2OutputOracleGenesisL2Output, - deployConfig.l2OutputOracleStartingBlockNumber, deployConfig.l2OutputOracleProposer, deployConfig.l2OutputOracleOwner, ], diff --git a/packages/contracts-governance/deploy-config/optimism-goerli.json b/packages/contracts-governance/deploy-config/optimism-goerli.json new file mode 100644 index 0000000000000..b8a75edd02a59 --- /dev/null +++ b/packages/contracts-governance/deploy-config/optimism-goerli.json @@ -0,0 +1,3 @@ +{ + "upgrader": "0xC30276833798867C1dBC5c468bf51cA900b44E4c" +} diff --git a/packages/contracts-governance/deploy-config/optimism-mainnet.json b/packages/contracts-governance/deploy-config/optimism-mainnet.json new file mode 100644 index 0000000000000..0b803c91d20d0 --- /dev/null +++ b/packages/contracts-governance/deploy-config/optimism-mainnet.json @@ -0,0 +1,3 @@ +{ + "upgrader": "0x2A82Ae142b2e62Cb7D10b55E323ACB1Cab663a26" +} diff --git a/packages/contracts-governance/deploy/000-mint-manager-impl.ts b/packages/contracts-governance/deploy/000-mint-manager-impl.ts new file mode 100644 index 0000000000000..bdb3617971fc1 --- /dev/null +++ b/packages/contracts-governance/deploy/000-mint-manager-impl.ts @@ -0,0 +1,92 @@ +import { DeployFunction } from 'hardhat-deploy/dist/types' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import 'hardhat-deploy' +import '@eth-optimism/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { sleep } from '@eth-optimism/core-utils' + +// $ cast call --rpc-url https://mainnet.optimism.io 0x4200000000000000000000000000000000000042 'owner()(address)' +// 0x724604DB3C8D86c906A27B610703fD0296Eb26D5 +// $ cast call --rpc-url https://mainnet.optimism.io 0x724604DB3C8D86c906A27B610703fD0296Eb26D5 'owner()(address)' +// 0x2A82Ae142b2e62Cb7D10b55E323ACB1Cab663a26 +// +// $ cast call --rpc-url https://goerli.optimism.io 0x4200000000000000000000000000000000000042 'owner()(address)' +// 0xB2DcB2Df7732030eD99241E5F9aEBB3Fb53eFCb6 +// $ cast call --rpc-url https://goerli.optimism.io 0xB2DcB2Df7732030eD99241E5F9aEBB3Fb53eFCb6 'owner()(address)' +// 0xC30276833798867C1dBC5c468bf51cA900b44E4c + +// Deployment steps: +// 1 - Deploy new MintManager implementation +// 2 - Multisig transaction calls `upgrade()` on the old MintManager +const deployFn: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + const upgrader = hre.deployConfig.upgrader + const governanceToken = '0x4200000000000000000000000000000000000042' + + if (upgrader === '' || upgrader === hre.ethers.constants.AddressZero) { + throw new Error('upgrader not set in deploy-config') + } + + // There is no artifact for the originally deployed MintManager + let oldImpl: string + if (hre.network.name === 'optimism-mainnet') { + oldImpl = '0x724604DB3C8D86c906A27B610703fD0296Eb26D5' + } else if (hre.network.name === 'optimism-goerli') { + oldImpl = '0xB2DcB2Df7732030eD99241E5F9aEBB3Fb53eFCb6' + } else { + throw new Error(`unknown network ${hre.network.name}`) + } + + await deploy('MintManager', { + from: deployer, + args: [upgrader, governanceToken], + log: true, + waitConfirmations: 1, + }) + + const GovernanceToken = await hre.ethers.getContractAt( + 'GovernanceToken', + '0x4200000000000000000000000000000000000042' + ) + + const Old__MintManager = await hre.ethers.getContractAt( + 'MintManager', + oldImpl + ) + const oldOwner = await Old__MintManager.owner() + + const getAddress = hre.ethers.utils.getAddress + + const Deployment__MintManager = await hre.deployments.get('MintManager') + const newImpl = Deployment__MintManager.address + + console.log() + console.log('Action is required to complete this deployment') + console.log( + 'Ownership of the GovernanceToken should be migrated to the newly deployed MintManager' + ) + console.log(`MintManager.owner() -> ${oldOwner}`) + console.log(`Call MintManager(${oldImpl}).upgrade(${newImpl})`) + console.log() + + while (true) { + const owner = await GovernanceToken.owner() + if (getAddress(owner) === getAddress(oldImpl)) { + console.log(`GovernanceToken.owner() is still old implementation`) + } else if (getAddress(owner) === getAddress(newImpl)) { + console.log(`GovernanceToken.owner() upgraded to new implementation!`) + break + } else { + throw new Error( + `GovernanceToken.owner() upgraded to unknown address ${owner}` + ) + } + await sleep(5000) + } +} + +deployFn.tags = ['MintManager'] + +export default deployFn diff --git a/packages/contracts-governance/deployments/optimism-goerli/.chainId b/packages/contracts-governance/deployments/optimism-goerli/.chainId new file mode 100644 index 0000000000000..1e59c84a3a515 --- /dev/null +++ b/packages/contracts-governance/deployments/optimism-goerli/.chainId @@ -0,0 +1 @@ +420 \ No newline at end of file diff --git a/packages/contracts-governance/deployments/optimism-goerli/MintManager.json b/packages/contracts-governance/deployments/optimism-goerli/MintManager.json new file mode 100644 index 0000000000000..d0dccf28d1aae --- /dev/null +++ b/packages/contracts-governance/deployments/optimism-goerli/MintManager.json @@ -0,0 +1,316 @@ +{ + "address": "0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_upgrader", + "type": "address" + }, + { + "internalType": "address", + "name": "_governanceToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINT_CAP", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINT_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governanceToken", + "outputs": [ + { + "internalType": "contract GovernanceToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintPermittedAfter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newMintManager", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xef34b41d22d24351e6ff22ffc48345eb42218c6c6403c950724a98ded6427c89", + "receipt": { + "to": null, + "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", + "contractAddress": "0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76", + "transactionIndex": 0, + "gasUsed": "880786", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000140000000000000000000000000100000000000000000000000001001000000000000000000000000000000000020000000000000000000800000000000000000000400000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x32d987eea82dca38607860e322e8e65da279102dd609137782217b7cc447d5cd", + "transactionHash": "0xef34b41d22d24351e6ff22ffc48345eb42218c6c6403c950724a98ded6427c89", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 1777450, + "transactionHash": "0xef34b41d22d24351e6ff22ffc48345eb42218c6c6403c950724a98ded6427c89", + "address": "0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x32d987eea82dca38607860e322e8e65da279102dd609137782217b7cc447d5cd" + }, + { + "transactionIndex": 0, + "blockNumber": 1777450, + "transactionHash": "0xef34b41d22d24351e6ff22ffc48345eb42218c6c6403c950724a98ded6427c89", + "address": "0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d", + "0x000000000000000000000000c30276833798867c1dbc5c468bf51ca900b44e4c" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x32d987eea82dca38607860e322e8e65da279102dd609137782217b7cc447d5cd" + } + ], + "blockNumber": 1777450, + "cumulativeGasUsed": "880786", + "status": 1, + "byzantium": true + }, + "args": [ + "0xC30276833798867C1dBC5c468bf51cA900b44E4c", + "0x4200000000000000000000000000000000000042" + ], + "numDeployments": 1, + "solcInputHash": "b1df373a9ed51b3903b61f56faa9a78f", + "metadata": "{\"compiler\":{\"version\":\"0.8.12+commit.f00d7308\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_upgrader\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_governanceToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINT_CAP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINT_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governanceToken\",\"outputs\":[{\"internalType\":\"contract GovernanceToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintPermittedAfter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newMintManager\",\"type\":\"address\"}],\"name\":\"upgrade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_governanceToken\":\"The governance token this contract can mint tokens of\",\"_upgrader\":\"The owner of this contract\"}},\"mint(address,uint256)\":{\"params\":{\"_account\":\"Address to mint new tokens to.\",\"_amount\":\"Amount of tokens to be minted.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address)\":{\"params\":{\"_newMintManager\":\"The MintManager to upgrade to\"}}},\"title\":\"MintManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DENOMINATOR()\":{\"notice\":\"The number of decimals for the MINT_CAP.\"},\"MINT_CAP()\":{\"notice\":\"The amount of tokens that can be minted per year. The value is a fixed point number with 4 decimals.\"},\"MINT_PERIOD()\":{\"notice\":\"The amount of time that must pass before the MINT_CAP number of tokens can be minted again.\"},\"governanceToken()\":{\"notice\":\"The GovernanceToken that the MintManager can mint tokens\"},\"mint(address,uint256)\":{\"notice\":\"Only the token owner is allowed to mint a certain amount of OP per year.\"},\"mintPermittedAfter()\":{\"notice\":\"Tracks the time of last mint\"},\"upgrade(address)\":{\"notice\":\"Upgrade the owner of the governance token to a new MintManager.\"}},\"notice\":\"Set as `owner` of the OP token and responsible for the token inflation schedule. Contract acts as the token \\\"mint manager\\\" with permission to the `mint` function only. Currently permitted to mint once per year of up to 2% of the total token supply. Upgradable to allow changes in the inflation schedule.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/MintManager.sol\":\"MintManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(\\n address delegatee,\\n uint256 nonce,\\n uint256 expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0xf5324a55ee9c0b4a840ea57c055ac9d046f88986ceef567e1cf68113e46a79c0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, _allowances[owner][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = _allowances[owner][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n }\\n _balances[to] += amount;\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Spend `amount` form the allowance of `owner` toward `spender`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0xdadd41acb749920eccf40aeaa8d291adf9751399a7343561bad13e7a8d99be0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xbbc8ac883ac3c0078ce5ad3e288fbb3ffcc8a30c3a98c0fda0114d64fc44fca2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n _spendAllowance(account, _msgSender(), amount);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x0d19410453cda55960a818e02bd7c18952a5c8fe7a3036e81f0d599f34487a7b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./draft-ERC20Permit.sol\\\";\\nimport \\\"../../../utils/math/Math.sol\\\";\\nimport \\\"../../../governance/utils/IVotes.sol\\\";\\nimport \\\"../../../utils/math/SafeCast.sol\\\";\\nimport \\\"../../../utils/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,\\n * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.\\n *\\n * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.\\n *\\n * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either\\n * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting\\n * power can be queried through the public accessors {getVotes} and {getPastVotes}.\\n *\\n * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it\\n * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.\\n *\\n * _Available since v4.2._\\n */\\nabstract contract ERC20Votes is IVotes, ERC20Permit {\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint224 votes;\\n }\\n\\n bytes32 private constant _DELEGATION_TYPEHASH =\\n keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n mapping(address => address) private _delegates;\\n mapping(address => Checkpoint[]) private _checkpoints;\\n Checkpoint[] private _totalSupplyCheckpoints;\\n\\n /**\\n * @dev Get the `pos`-th checkpoint for `account`.\\n */\\n function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {\\n return _checkpoints[account][pos];\\n }\\n\\n /**\\n * @dev Get number of checkpoints for `account`.\\n */\\n function numCheckpoints(address account) public view virtual returns (uint32) {\\n return SafeCast.toUint32(_checkpoints[account].length);\\n }\\n\\n /**\\n * @dev Get the address `account` is currently delegating to.\\n */\\n function delegates(address account) public view virtual override returns (address) {\\n return _delegates[account];\\n }\\n\\n /**\\n * @dev Gets the current votes balance for `account`\\n */\\n function getVotes(address account) public view virtual override returns (uint256) {\\n uint256 pos = _checkpoints[account].length;\\n return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;\\n }\\n\\n /**\\n * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.\\n *\\n * Requirements:\\n *\\n * - `blockNumber` must have been already mined\\n */\\n function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {\\n require(blockNumber < block.number, \\\"ERC20Votes: block not yet mined\\\");\\n return _checkpointsLookup(_checkpoints[account], blockNumber);\\n }\\n\\n /**\\n * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.\\n * It is but NOT the sum of all the delegated votes!\\n *\\n * Requirements:\\n *\\n * - `blockNumber` must have been already mined\\n */\\n function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {\\n require(blockNumber < block.number, \\\"ERC20Votes: block not yet mined\\\");\\n return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);\\n }\\n\\n /**\\n * @dev Lookup a value in a list of (sorted) checkpoints.\\n */\\n function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {\\n // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.\\n //\\n // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).\\n // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.\\n // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)\\n // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high)\\n // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not\\n // out of bounds (in which case we're looking too far in the past and the result is 0).\\n // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is\\n // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out\\n // the same.\\n uint256 high = ckpts.length;\\n uint256 low = 0;\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n if (ckpts[mid].fromBlock > blockNumber) {\\n high = mid;\\n } else {\\n low = mid + 1;\\n }\\n }\\n\\n return high == 0 ? 0 : ckpts[high - 1].votes;\\n }\\n\\n /**\\n * @dev Delegate votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) public virtual override {\\n _delegate(_msgSender(), delegatee);\\n }\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`\\n */\\n function delegateBySig(\\n address delegatee,\\n uint256 nonce,\\n uint256 expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override {\\n require(block.timestamp <= expiry, \\\"ERC20Votes: signature expired\\\");\\n address signer = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),\\n v,\\n r,\\n s\\n );\\n require(nonce == _useNonce(signer), \\\"ERC20Votes: invalid nonce\\\");\\n _delegate(signer, delegatee);\\n }\\n\\n /**\\n * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).\\n */\\n function _maxSupply() internal view virtual returns (uint224) {\\n return type(uint224).max;\\n }\\n\\n /**\\n * @dev Snapshots the totalSupply after it has been increased.\\n */\\n function _mint(address account, uint256 amount) internal virtual override {\\n super._mint(account, amount);\\n require(totalSupply() <= _maxSupply(), \\\"ERC20Votes: total supply risks overflowing votes\\\");\\n\\n _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);\\n }\\n\\n /**\\n * @dev Snapshots the totalSupply after it has been decreased.\\n */\\n function _burn(address account, uint256 amount) internal virtual override {\\n super._burn(account, amount);\\n\\n _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);\\n }\\n\\n /**\\n * @dev Move voting power when tokens are transferred.\\n *\\n * Emits a {DelegateVotesChanged} event.\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override {\\n super._afterTokenTransfer(from, to, amount);\\n\\n _moveVotingPower(delegates(from), delegates(to), amount);\\n }\\n\\n /**\\n * @dev Change delegation for `delegator` to `delegatee`.\\n *\\n * Emits events {DelegateChanged} and {DelegateVotesChanged}.\\n */\\n function _delegate(address delegator, address delegatee) internal virtual {\\n address currentDelegate = delegates(delegator);\\n uint256 delegatorBalance = balanceOf(delegator);\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveVotingPower(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _moveVotingPower(\\n address src,\\n address dst,\\n uint256 amount\\n ) private {\\n if (src != dst && amount > 0) {\\n if (src != address(0)) {\\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);\\n emit DelegateVotesChanged(src, oldWeight, newWeight);\\n }\\n\\n if (dst != address(0)) {\\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);\\n emit DelegateVotesChanged(dst, oldWeight, newWeight);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(\\n Checkpoint[] storage ckpts,\\n function(uint256, uint256) view returns (uint256) op,\\n uint256 delta\\n ) private returns (uint256 oldWeight, uint256 newWeight) {\\n uint256 pos = ckpts.length;\\n oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes;\\n newWeight = op(oldWeight, delta);\\n\\n if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {\\n ckpts[pos - 1].votes = SafeCast.toUint224(newWeight);\\n } else {\\n ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)}));\\n }\\n }\\n\\n function _add(uint256 a, uint256 b) private pure returns (uint256) {\\n return a + b;\\n }\\n\\n function _subtract(uint256 a, uint256 b) private pure returns (uint256) {\\n return a - b;\\n }\\n}\\n\",\"keccak256\":\"0x7fd2492be0468be4662081ee25cde38a31e4a0ceca0fed10160462389013910f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-ERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./draft-IERC20Permit.sol\\\";\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"../../../utils/cryptography/ECDSA.sol\\\";\\nimport \\\"../../../utils/Counters.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n *\\n * _Available since v3.4._\\n */\\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\\n using Counters for Counters.Counter;\\n\\n mapping(address => Counters.Counter) private _nonces;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 private immutable _PERMIT_TYPEHASH =\\n keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n\\n /**\\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n *\\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\\n */\\n constructor(string memory name) EIP712(name, \\\"1\\\") {}\\n\\n /**\\n * @dev See {IERC20Permit-permit}.\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override {\\n require(block.timestamp <= deadline, \\\"ERC20Permit: expired deadline\\\");\\n\\n bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\\n\\n bytes32 hash = _hashTypedDataV4(structHash);\\n\\n address signer = ECDSA.recover(hash, v, r, s);\\n require(signer == owner, \\\"ERC20Permit: invalid signature\\\");\\n\\n _approve(owner, spender, value);\\n }\\n\\n /**\\n * @dev See {IERC20Permit-nonces}.\\n */\\n function nonces(address owner) public view virtual override returns (uint256) {\\n return _nonces[owner].current();\\n }\\n\\n /**\\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\\n return _domainSeparatorV4();\\n }\\n\\n /**\\n * @dev \\\"Consume a nonce\\\": return the current value and increment.\\n *\\n * _Available since v4.1._\\n */\\n function _useNonce(address owner) internal virtual returns (uint256 current) {\\n Counters.Counter storage nonce = _nonces[owner];\\n current = nonce.current();\\n nonce.increment();\\n }\\n}\\n\",\"keccak256\":\"0x8a763ef5625e97f5287c7ddd5ede434129069e15d83bf0a68ad10a5e56ccb439\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Counters.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n */\\nlibrary Counters {\\n struct Counter {\\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n // this feature: see https://github.com/ethereum/solidity/issues/4637\\n uint256 _value; // default: 0\\n }\\n\\n function current(Counter storage counter) internal view returns (uint256) {\\n return counter._value;\\n }\\n\\n function increment(Counter storage counter) internal {\\n unchecked {\\n counter._value += 1;\\n }\\n }\\n\\n function decrement(Counter storage counter) internal {\\n uint256 value = counter._value;\\n require(value > 0, \\\"Counter: decrement overflow\\\");\\n unchecked {\\n counter._value = value - 1;\\n }\\n }\\n\\n function reset(Counter storage counter) internal {\\n counter._value = 0;\\n }\\n}\\n\",\"keccak256\":\"0xf0018c2440fbe238dd3a8732fa8e17a0f9dce84d31451dc8a32f6d62b349c9f1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n } else if (error == RecoverError.InvalidSignatureV) {\\n revert(\\\"ECDSA: invalid signature 'v' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n // Check the signature length\\n // - case 65: r,s,v signature (standard)\\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else if (signature.length == 64) {\\n bytes32 r;\\n bytes32 vs;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly {\\n r := mload(add(signature, 0x20))\\n vs := mload(add(signature, 0x40))\\n }\\n return tryRecover(hash, r, vs);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n if (v != 27 && v != 28) {\\n return (address(0), RecoverError.InvalidSignatureV);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x3c07f43e60e099b3b157243b3152722e73b80eeb7985c2cd73712828d7f7da29\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x6688fad58b9ec0286d40fa957152e575d5d8bd4c3aa80985efdb11b44f776ae7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a / b + (a % b == 0 ? 0 : 1);\\n }\\n}\\n\",\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits.\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128) {\\n require(value >= type(int128).min && value <= type(int128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return int128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64) {\\n require(value >= type(int64).min && value <= type(int64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return int64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32) {\\n require(value >= type(int32).min && value <= type(int32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return int32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16) {\\n require(value >= type(int16).min && value <= type(int16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return int16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits.\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8) {\\n require(value >= type(int8).min && value <= type(int8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return int8(value);\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x5c6caab697d302ad7eb59c234a4d2dbc965c1bae87709bd2850060b7695b28c7\",\"license\":\"MIT\"},\"contracts/GovernanceToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * @dev The Optimism token used in governance and supporting voting and delegation.\\n * Implements EIP 2612 allowing signed approvals.\\n * Contract is \\\"owned\\\" by a `MintManager` instance with permission to the `mint` function only,\\n * for the purposes of enforcing the token inflation schedule.\\n */\\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\\n /**\\n * @dev Constructor.\\n */\\n constructor() ERC20(\\\"Optimism\\\", \\\"OP\\\") ERC20Permit(\\\"Optimism\\\") {}\\n\\n function mint(address _account, uint256 _amount) public onlyOwner {\\n _mint(_account, _amount);\\n }\\n\\n // The following functions are overrides required by Solidity.\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal override(ERC20, ERC20Votes) {\\n super._afterTokenTransfer(from, to, amount);\\n }\\n\\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\\n super._mint(to, amount);\\n }\\n\\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\\n super._burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9686248fc10e71c30b05bc86a7b7749f12f74e5701c9d73b15ca9f75b9093839\",\"license\":\"MIT\"},\"contracts/MintManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.12;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"./GovernanceToken.sol\\\";\\n\\n/**\\n * @title MintManager\\n * @notice Set as `owner` of the OP token and responsible for the token inflation schedule.\\n * Contract acts as the token \\\"mint manager\\\" with permission to the `mint` function only.\\n * Currently permitted to mint once per year of up to 2% of the total token supply.\\n * Upgradable to allow changes in the inflation schedule.\\n */\\ncontract MintManager is Ownable {\\n /**\\n * @notice The GovernanceToken that the MintManager can mint tokens\\n */\\n GovernanceToken public immutable governanceToken;\\n\\n /**\\n * @notice The amount of tokens that can be minted per year. The value is a fixed\\n * point number with 4 decimals.\\n */\\n uint256 public constant MINT_CAP = 20; // 2%\\n\\n /**\\n * @notice The number of decimals for the MINT_CAP.\\n */\\n uint256 public constant DENOMINATOR = 1000;\\n\\n /**\\n * @notice The amount of time that must pass before the MINT_CAP number of tokens can\\n * be minted again.\\n */\\n uint256 public constant MINT_PERIOD = 365 days;\\n\\n /**\\n * @notice Tracks the time of last mint\\n */\\n uint256 public mintPermittedAfter;\\n\\n /**\\n * @param _upgrader The owner of this contract\\n * @param _governanceToken The governance token this contract can mint\\n * tokens of\\n */\\n constructor(address _upgrader, address _governanceToken) {\\n transferOwnership(_upgrader);\\n governanceToken = GovernanceToken(_governanceToken);\\n }\\n\\n /**\\n * @notice Only the token owner is allowed to mint a certain amount of OP per year.\\n *\\n * @param _account Address to mint new tokens to.\\n * @param _amount Amount of tokens to be minted.\\n */\\n function mint(address _account, uint256 _amount) public onlyOwner {\\n if (mintPermittedAfter > 0) {\\n require(mintPermittedAfter <= block.timestamp, \\\"OP: minting not permitted yet\\\");\\n\\n require(\\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\\n \\\"OP: mint amount exceeds cap\\\"\\n );\\n }\\n\\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\\n\\n governanceToken.mint(_account, _amount);\\n }\\n\\n /**\\n * @notice Upgrade the owner of the governance token to a new MintManager.\\n *\\n * @param _newMintManager The MintManager to upgrade to\\n */\\n function upgrade(address _newMintManager) public onlyOwner {\\n require(_newMintManager != address(0), \\\"OP: Mint manager cannot be empty\\\");\\n\\n governanceToken.transferOwnership(_newMintManager);\\n }\\n}\\n\",\"keccak256\":\"0x502e1e705839a9840823fe4c2eef2cf7f717b548c2259c6c5cf5e62753fbd940\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b50604051620012f1380380620012f1833981810160405281019062000037919062000319565b620000576200004b620000a460201b60201c565b620000ac60201b60201c565b62000068826200017060201b60201c565b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505050506200047b565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b62000180620000a460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620001a66200028660201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620001ff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001f690620003c1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000272576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002699062000459565b60405180910390fd5b6200028381620000ac60201b60201c565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620002e182620002b4565b9050919050565b620002f381620002d4565b8114620002ff57600080fd5b50565b6000815190506200031381620002e8565b92915050565b60008060408385031215620003335762000332620002af565b5b6000620003438582860162000302565b9250506020620003568582860162000302565b9150509250929050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000620003a960208362000360565b9150620003b68262000371565b602082019050919050565b60006020820190508181036000830152620003dc816200039a565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006200044160268362000360565b91506200044e82620003e3565b604082019050919050565b60006020820190508181036000830152620004748162000432565b9050919050565b608051610e45620004ac600039600081816102a8015281816104070152818161050301526107500152610e456000f3fe608060405234801561001057600080fd5b506004361061009d5760003560e01c80638da5cb5b116100665780638da5cb5b14610120578063918f86741461013e57806398f1312e1461015c578063f2fde38b1461017a578063f96dae0a146101965761009d565b8062f8900c146100a25780630900f010146100c057806340c10f19146100dc578063715018a6146100f857806383ea6e9714610102575b600080fd5b6100aa6101b4565b6040516100b79190610857565b60405180910390f35b6100da60048036038101906100d591906108d5565b6101ba565b005b6100f660048036038101906100f1919061092e565b610334565b005b610100610592565b005b61010a61061a565b6040516101179190610857565b60405180910390f35b610128610622565b604051610135919061097d565b60405180910390f35b61014661064b565b6040516101539190610857565b60405180910390f35b610164610651565b6040516101719190610857565b60405180910390f35b610194600480360381019061018f91906108d5565b610656565b005b61019e61074e565b6040516101ab91906109f7565b60405180910390f35b60015481565b6101c2610772565b73ffffffffffffffffffffffffffffffffffffffff166101e0610622565b73ffffffffffffffffffffffffffffffffffffffff1614610236576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022d90610a6f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156102a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161029d90610adb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f2fde38b826040518263ffffffff1660e01b81526004016102ff919061097d565b600060405180830381600087803b15801561031957600080fd5b505af115801561032d573d6000803e3d6000fd5b5050505050565b61033c610772565b73ffffffffffffffffffffffffffffffffffffffff1661035a610622565b73ffffffffffffffffffffffffffffffffffffffff16146103b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a790610a6f565b60405180910390fd5b600060015411156104eb57426001541115610400576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f790610b47565b60405180910390fd5b6103e860147f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610470573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104949190610b7c565b61049e9190610bd8565b6104a89190610c61565b8111156104ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e190610cde565b60405180910390fd5b5b6301e13380426104fb9190610cfe565b6001819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166340c10f1983836040518363ffffffff1660e01b815260040161055c929190610d54565b600060405180830381600087803b15801561057657600080fd5b505af115801561058a573d6000803e3d6000fd5b505050505050565b61059a610772565b73ffffffffffffffffffffffffffffffffffffffff166105b8610622565b73ffffffffffffffffffffffffffffffffffffffff161461060e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060590610a6f565b60405180910390fd5b610618600061077a565b565b6301e1338081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6103e881565b601481565b61065e610772565b73ffffffffffffffffffffffffffffffffffffffff1661067c610622565b73ffffffffffffffffffffffffffffffffffffffff16146106d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c990610a6f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073990610def565b60405180910390fd5b61074b8161077a565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b6108518161083e565b82525050565b600060208201905061086c6000830184610848565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006108a282610877565b9050919050565b6108b281610897565b81146108bd57600080fd5b50565b6000813590506108cf816108a9565b92915050565b6000602082840312156108eb576108ea610872565b5b60006108f9848285016108c0565b91505092915050565b61090b8161083e565b811461091657600080fd5b50565b60008135905061092881610902565b92915050565b6000806040838503121561094557610944610872565b5b6000610953858286016108c0565b925050602061096485828601610919565b9150509250929050565b61097781610897565b82525050565b6000602082019050610992600083018461096e565b92915050565b6000819050919050565b60006109bd6109b86109b384610877565b610998565b610877565b9050919050565b60006109cf826109a2565b9050919050565b60006109e1826109c4565b9050919050565b6109f1816109d6565b82525050565b6000602082019050610a0c60008301846109e8565b92915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610a59602083610a12565b9150610a6482610a23565b602082019050919050565b60006020820190508181036000830152610a8881610a4c565b9050919050565b7f4f503a204d696e74206d616e616765722063616e6e6f7420626520656d707479600082015250565b6000610ac5602083610a12565b9150610ad082610a8f565b602082019050919050565b60006020820190508181036000830152610af481610ab8565b9050919050565b7f4f503a206d696e74696e67206e6f74207065726d697474656420796574000000600082015250565b6000610b31601d83610a12565b9150610b3c82610afb565b602082019050919050565b60006020820190508181036000830152610b6081610b24565b9050919050565b600081519050610b7681610902565b92915050565b600060208284031215610b9257610b91610872565b5b6000610ba084828501610b67565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610be38261083e565b9150610bee8361083e565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610c2757610c26610ba9565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000610c6c8261083e565b9150610c778361083e565b925082610c8757610c86610c32565b5b828204905092915050565b7f4f503a206d696e7420616d6f756e742065786365656473206361700000000000600082015250565b6000610cc8601b83610a12565b9150610cd382610c92565b602082019050919050565b60006020820190508181036000830152610cf781610cbb565b9050919050565b6000610d098261083e565b9150610d148361083e565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610d4957610d48610ba9565b5b828201905092915050565b6000604082019050610d69600083018561096e565b610d766020830184610848565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610dd9602683610a12565b9150610de482610d7d565b604082019050919050565b60006020820190508181036000830152610e0881610dcc565b905091905056fea2646970667358221220d6ef0f15f2581f08c298ff8c67408d75a27f67742459525e88193c029a7a0bcf64736f6c634300080c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061009d5760003560e01c80638da5cb5b116100665780638da5cb5b14610120578063918f86741461013e57806398f1312e1461015c578063f2fde38b1461017a578063f96dae0a146101965761009d565b8062f8900c146100a25780630900f010146100c057806340c10f19146100dc578063715018a6146100f857806383ea6e9714610102575b600080fd5b6100aa6101b4565b6040516100b79190610857565b60405180910390f35b6100da60048036038101906100d591906108d5565b6101ba565b005b6100f660048036038101906100f1919061092e565b610334565b005b610100610592565b005b61010a61061a565b6040516101179190610857565b60405180910390f35b610128610622565b604051610135919061097d565b60405180910390f35b61014661064b565b6040516101539190610857565b60405180910390f35b610164610651565b6040516101719190610857565b60405180910390f35b610194600480360381019061018f91906108d5565b610656565b005b61019e61074e565b6040516101ab91906109f7565b60405180910390f35b60015481565b6101c2610772565b73ffffffffffffffffffffffffffffffffffffffff166101e0610622565b73ffffffffffffffffffffffffffffffffffffffff1614610236576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022d90610a6f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156102a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161029d90610adb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f2fde38b826040518263ffffffff1660e01b81526004016102ff919061097d565b600060405180830381600087803b15801561031957600080fd5b505af115801561032d573d6000803e3d6000fd5b5050505050565b61033c610772565b73ffffffffffffffffffffffffffffffffffffffff1661035a610622565b73ffffffffffffffffffffffffffffffffffffffff16146103b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a790610a6f565b60405180910390fd5b600060015411156104eb57426001541115610400576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f790610b47565b60405180910390fd5b6103e860147f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610470573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104949190610b7c565b61049e9190610bd8565b6104a89190610c61565b8111156104ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e190610cde565b60405180910390fd5b5b6301e13380426104fb9190610cfe565b6001819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166340c10f1983836040518363ffffffff1660e01b815260040161055c929190610d54565b600060405180830381600087803b15801561057657600080fd5b505af115801561058a573d6000803e3d6000fd5b505050505050565b61059a610772565b73ffffffffffffffffffffffffffffffffffffffff166105b8610622565b73ffffffffffffffffffffffffffffffffffffffff161461060e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060590610a6f565b60405180910390fd5b610618600061077a565b565b6301e1338081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6103e881565b601481565b61065e610772565b73ffffffffffffffffffffffffffffffffffffffff1661067c610622565b73ffffffffffffffffffffffffffffffffffffffff16146106d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c990610a6f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073990610def565b60405180910390fd5b61074b8161077a565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b6108518161083e565b82525050565b600060208201905061086c6000830184610848565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006108a282610877565b9050919050565b6108b281610897565b81146108bd57600080fd5b50565b6000813590506108cf816108a9565b92915050565b6000602082840312156108eb576108ea610872565b5b60006108f9848285016108c0565b91505092915050565b61090b8161083e565b811461091657600080fd5b50565b60008135905061092881610902565b92915050565b6000806040838503121561094557610944610872565b5b6000610953858286016108c0565b925050602061096485828601610919565b9150509250929050565b61097781610897565b82525050565b6000602082019050610992600083018461096e565b92915050565b6000819050919050565b60006109bd6109b86109b384610877565b610998565b610877565b9050919050565b60006109cf826109a2565b9050919050565b60006109e1826109c4565b9050919050565b6109f1816109d6565b82525050565b6000602082019050610a0c60008301846109e8565b92915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610a59602083610a12565b9150610a6482610a23565b602082019050919050565b60006020820190508181036000830152610a8881610a4c565b9050919050565b7f4f503a204d696e74206d616e616765722063616e6e6f7420626520656d707479600082015250565b6000610ac5602083610a12565b9150610ad082610a8f565b602082019050919050565b60006020820190508181036000830152610af481610ab8565b9050919050565b7f4f503a206d696e74696e67206e6f74207065726d697474656420796574000000600082015250565b6000610b31601d83610a12565b9150610b3c82610afb565b602082019050919050565b60006020820190508181036000830152610b6081610b24565b9050919050565b600081519050610b7681610902565b92915050565b600060208284031215610b9257610b91610872565b5b6000610ba084828501610b67565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610be38261083e565b9150610bee8361083e565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610c2757610c26610ba9565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000610c6c8261083e565b9150610c778361083e565b925082610c8757610c86610c32565b5b828204905092915050565b7f4f503a206d696e7420616d6f756e742065786365656473206361700000000000600082015250565b6000610cc8601b83610a12565b9150610cd382610c92565b602082019050919050565b60006020820190508181036000830152610cf781610cbb565b9050919050565b6000610d098261083e565b9150610d148361083e565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610d4957610d48610ba9565b5b828201905092915050565b6000604082019050610d69600083018561096e565b610d766020830184610848565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610dd9602683610a12565b9150610de482610d7d565b604082019050919050565b60006020820190508181036000830152610e0881610dcc565b905091905056fea2646970667358221220d6ef0f15f2581f08c298ff8c67408d75a27f67742459525e88193c029a7a0bcf64736f6c634300080c0033", + "devdoc": { + "kind": "dev", + "methods": { + "constructor": { + "params": { + "_governanceToken": "The governance token this contract can mint tokens of", + "_upgrader": "The owner of this contract" + } + }, + "mint(address,uint256)": { + "params": { + "_account": "Address to mint new tokens to.", + "_amount": "Amount of tokens to be minted." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgrade(address)": { + "params": { + "_newMintManager": "The MintManager to upgrade to" + } + } + }, + "title": "MintManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "DENOMINATOR()": { + "notice": "The number of decimals for the MINT_CAP." + }, + "MINT_CAP()": { + "notice": "The amount of tokens that can be minted per year. The value is a fixed point number with 4 decimals." + }, + "MINT_PERIOD()": { + "notice": "The amount of time that must pass before the MINT_CAP number of tokens can be minted again." + }, + "governanceToken()": { + "notice": "The GovernanceToken that the MintManager can mint tokens" + }, + "mint(address,uint256)": { + "notice": "Only the token owner is allowed to mint a certain amount of OP per year." + }, + "mintPermittedAfter()": { + "notice": "Tracks the time of last mint" + }, + "upgrade(address)": { + "notice": "Upgrade the owner of the governance token to a new MintManager." + } + }, + "notice": "Set as `owner` of the OP token and responsible for the token inflation schedule. Contract acts as the token \"mint manager\" with permission to the `mint` function only. Currently permitted to mint once per year of up to 2% of the total token supply. Upgradable to allow changes in the inflation schedule.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/MintManager.sol:MintManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3573, + "contract": "contracts/MintManager.sol:MintManager", + "label": "mintPermittedAfter", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/contracts-governance/deployments/optimism-goerli/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json b/packages/contracts-governance/deployments/optimism-goerli/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json new file mode 100644 index 0000000000000..b0bf9b8a4dfb4 --- /dev/null +++ b/packages/contracts-governance/deployments/optimism-goerli/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "contracts/GovernanceToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @dev The Optimism token used in governance and supporting voting and delegation.\n * Implements EIP 2612 allowing signed approvals.\n * Contract is \"owned\" by a `MintManager` instance with permission to the `mint` function only,\n * for the purposes of enforcing the token inflation schedule.\n */\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\n /**\n * @dev Constructor.\n */\n constructor() ERC20(\"Optimism\", \"OP\") ERC20Permit(\"Optimism\") {}\n\n function mint(address _account, uint256 _amount) public onlyOwner {\n _mint(_account, _amount);\n }\n\n // The following functions are overrides required by Solidity.\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override(ERC20, ERC20Votes) {\n super._afterTokenTransfer(from, to, amount);\n }\n\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, _allowances[owner][spender] + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = _allowances[owner][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Spend `amount` form the allowance of `owner` toward `spender`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./draft-ERC20Permit.sol\";\nimport \"../../../utils/math/Math.sol\";\nimport \"../../../governance/utils/IVotes.sol\";\nimport \"../../../utils/math/SafeCast.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\n\n/**\n * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,\n * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.\n *\n * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.\n *\n * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either\n * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting\n * power can be queried through the public accessors {getVotes} and {getPastVotes}.\n *\n * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it\n * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.\n *\n * _Available since v4.2._\n */\nabstract contract ERC20Votes is IVotes, ERC20Permit {\n struct Checkpoint {\n uint32 fromBlock;\n uint224 votes;\n }\n\n bytes32 private constant _DELEGATION_TYPEHASH =\n keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n mapping(address => address) private _delegates;\n mapping(address => Checkpoint[]) private _checkpoints;\n Checkpoint[] private _totalSupplyCheckpoints;\n\n /**\n * @dev Get the `pos`-th checkpoint for `account`.\n */\n function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {\n return _checkpoints[account][pos];\n }\n\n /**\n * @dev Get number of checkpoints for `account`.\n */\n function numCheckpoints(address account) public view virtual returns (uint32) {\n return SafeCast.toUint32(_checkpoints[account].length);\n }\n\n /**\n * @dev Get the address `account` is currently delegating to.\n */\n function delegates(address account) public view virtual override returns (address) {\n return _delegates[account];\n }\n\n /**\n * @dev Gets the current votes balance for `account`\n */\n function getVotes(address account) public view virtual override returns (uint256) {\n uint256 pos = _checkpoints[account].length;\n return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;\n }\n\n /**\n * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.\n *\n * Requirements:\n *\n * - `blockNumber` must have been already mined\n */\n function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {\n require(blockNumber < block.number, \"ERC20Votes: block not yet mined\");\n return _checkpointsLookup(_checkpoints[account], blockNumber);\n }\n\n /**\n * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.\n * It is but NOT the sum of all the delegated votes!\n *\n * Requirements:\n *\n * - `blockNumber` must have been already mined\n */\n function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {\n require(blockNumber < block.number, \"ERC20Votes: block not yet mined\");\n return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);\n }\n\n /**\n * @dev Lookup a value in a list of (sorted) checkpoints.\n */\n function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {\n // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.\n //\n // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).\n // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.\n // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)\n // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high)\n // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not\n // out of bounds (in which case we're looking too far in the past and the result is 0).\n // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is\n // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out\n // the same.\n uint256 high = ckpts.length;\n uint256 low = 0;\n while (low < high) {\n uint256 mid = Math.average(low, high);\n if (ckpts[mid].fromBlock > blockNumber) {\n high = mid;\n } else {\n low = mid + 1;\n }\n }\n\n return high == 0 ? 0 : ckpts[high - 1].votes;\n }\n\n /**\n * @dev Delegate votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) public virtual override {\n _delegate(_msgSender(), delegatee);\n }\n\n /**\n * @dev Delegates votes from signer to `delegatee`\n */\n function delegateBySig(\n address delegatee,\n uint256 nonce,\n uint256 expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n require(block.timestamp <= expiry, \"ERC20Votes: signature expired\");\n address signer = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),\n v,\n r,\n s\n );\n require(nonce == _useNonce(signer), \"ERC20Votes: invalid nonce\");\n _delegate(signer, delegatee);\n }\n\n /**\n * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).\n */\n function _maxSupply() internal view virtual returns (uint224) {\n return type(uint224).max;\n }\n\n /**\n * @dev Snapshots the totalSupply after it has been increased.\n */\n function _mint(address account, uint256 amount) internal virtual override {\n super._mint(account, amount);\n require(totalSupply() <= _maxSupply(), \"ERC20Votes: total supply risks overflowing votes\");\n\n _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);\n }\n\n /**\n * @dev Snapshots the totalSupply after it has been decreased.\n */\n function _burn(address account, uint256 amount) internal virtual override {\n super._burn(account, amount);\n\n _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);\n }\n\n /**\n * @dev Move voting power when tokens are transferred.\n *\n * Emits a {DelegateVotesChanged} event.\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._afterTokenTransfer(from, to, amount);\n\n _moveVotingPower(delegates(from), delegates(to), amount);\n }\n\n /**\n * @dev Change delegation for `delegator` to `delegatee`.\n *\n * Emits events {DelegateChanged} and {DelegateVotesChanged}.\n */\n function _delegate(address delegator, address delegatee) internal virtual {\n address currentDelegate = delegates(delegator);\n uint256 delegatorBalance = balanceOf(delegator);\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n _moveVotingPower(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _moveVotingPower(\n address src,\n address dst,\n uint256 amount\n ) private {\n if (src != dst && amount > 0) {\n if (src != address(0)) {\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);\n emit DelegateVotesChanged(src, oldWeight, newWeight);\n }\n\n if (dst != address(0)) {\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);\n emit DelegateVotesChanged(dst, oldWeight, newWeight);\n }\n }\n }\n\n function _writeCheckpoint(\n Checkpoint[] storage ckpts,\n function(uint256, uint256) view returns (uint256) op,\n uint256 delta\n ) private returns (uint256 oldWeight, uint256 newWeight) {\n uint256 pos = ckpts.length;\n oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes;\n newWeight = op(oldWeight, delta);\n\n if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {\n ckpts[pos - 1].votes = SafeCast.toUint224(newWeight);\n } else {\n ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)}));\n }\n }\n\n function _add(uint256 a, uint256 b) private pure returns (uint256) {\n return a + b;\n }\n\n function _subtract(uint256 a, uint256 b) private pure returns (uint256) {\n return a - b;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-ERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./draft-IERC20Permit.sol\";\nimport \"../ERC20.sol\";\nimport \"../../../utils/cryptography/draft-EIP712.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\nimport \"../../../utils/Counters.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping(address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) EIP712(name, \"1\") {}\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view virtual override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n\n /**\n * @dev \"Consume a nonce\": return the current value and increment.\n *\n * _Available since v4.1._\n */\n function _useNonce(address owner) internal virtual returns (uint256 current) {\n Counters.Counter storage nonce = _nonces[owner];\n current = nonce.current();\n nonce.increment();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a / b + (a % b == 0 ? 0 : 1);\n }\n}\n" + }, + "@openzeppelin/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(\n address delegatee,\n uint256 nonce,\n uint256 expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128) {\n require(value >= type(int128).min && value <= type(int128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return int128(value);\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64) {\n require(value >= type(int64).min && value <= type(int64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return int64(value);\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32) {\n require(value >= type(int32).min && value <= type(int32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return int32(value);\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16) {\n require(value >= type(int16).min && value <= type(int16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return int16(value);\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8) {\n require(value >= type(int8).min && value <= type(int8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return int8(value);\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 && v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "contracts/MintManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./GovernanceToken.sol\";\n\n/**\n * @title MintManager\n * @notice Set as `owner` of the OP token and responsible for the token inflation schedule.\n * Contract acts as the token \"mint manager\" with permission to the `mint` function only.\n * Currently permitted to mint once per year of up to 2% of the total token supply.\n * Upgradable to allow changes in the inflation schedule.\n */\ncontract MintManager is Ownable {\n /**\n * @notice The GovernanceToken that the MintManager can mint tokens\n */\n GovernanceToken public immutable governanceToken;\n\n /**\n * @notice The amount of tokens that can be minted per year. The value is a fixed\n * point number with 4 decimals.\n */\n uint256 public constant MINT_CAP = 20; // 2%\n\n /**\n * @notice The number of decimals for the MINT_CAP.\n */\n uint256 public constant DENOMINATOR = 1000;\n\n /**\n * @notice The amount of time that must pass before the MINT_CAP number of tokens can\n * be minted again.\n */\n uint256 public constant MINT_PERIOD = 365 days;\n\n /**\n * @notice Tracks the time of last mint\n */\n uint256 public mintPermittedAfter;\n\n /**\n * @param _upgrader The owner of this contract\n * @param _governanceToken The governance token this contract can mint\n * tokens of\n */\n constructor(address _upgrader, address _governanceToken) {\n transferOwnership(_upgrader);\n governanceToken = GovernanceToken(_governanceToken);\n }\n\n /**\n * @notice Only the token owner is allowed to mint a certain amount of OP per year.\n *\n * @param _account Address to mint new tokens to.\n * @param _amount Amount of tokens to be minted.\n */\n function mint(address _account, uint256 _amount) public onlyOwner {\n if (mintPermittedAfter > 0) {\n require(mintPermittedAfter <= block.timestamp, \"OP: minting not permitted yet\");\n\n require(\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\n \"OP: mint amount exceeds cap\"\n );\n }\n\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\n\n governanceToken.mint(_account, _amount);\n }\n\n /**\n * @notice Upgrade the owner of the governance token to a new MintManager.\n *\n * @param _newMintManager The MintManager to upgrade to\n */\n function upgrade(address _newMintManager) public onlyOwner {\n require(_newMintManager != address(0), \"OP: Mint manager cannot be empty\");\n\n governanceToken.transferOwnership(_newMintManager);\n }\n}\n" + }, + "contracts/test/TestERC20.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.8.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n constructor(\n string memory name_,\n string memory symbol_,\n uint256 amountToMint\n ) ERC20(name_, symbol_) {\n setBalance(msg.sender, amountToMint);\n }\n\n // sets the balance of the address\n // this mints/burns the amount depending on the current balance\n function setBalance(address to, uint256 amount) public {\n uint256 old = balanceOf(to);\n if (old < amount) {\n _mint(to, amount - old);\n } else if (old > amount) {\n _burn(to, old - amount);\n }\n }\n}\n" + }, + "contracts/MerkleDistributor.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.8.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"./interfaces/IMerkleDistributor.sol\";\n\ncontract MerkleDistributor is IMerkleDistributor {\n address public immutable override token;\n bytes32 public immutable override merkleRoot;\n\n uint256 public constant ONE_YEAR_IN_SECONDS = 31_536_000;\n uint256 public immutable activationTimestamp;\n address public immutable airdropTreasury;\n bool public isActive;\n\n // This is a packed array of booleans.\n mapping(uint256 => uint256) private claimedBitMap;\n\n event Finalised(address indexed calledBy, uint256 timestamp, uint256 unclaimedAmount);\n\n constructor(\n address token_,\n bytes32 merkleRoot_,\n address _treasury\n ) {\n token = token_;\n merkleRoot = merkleRoot_;\n\n activationTimestamp = block.timestamp;\n isActive = true;\n airdropTreasury = _treasury;\n }\n\n function isClaimed(uint256 index) public view override returns (bool) {\n uint256 claimedWordIndex = index / 256;\n uint256 claimedBitIndex = index % 256;\n uint256 claimedWord = claimedBitMap[claimedWordIndex];\n uint256 mask = (1 << claimedBitIndex);\n return claimedWord & mask == mask;\n }\n\n function _setClaimed(uint256 index) private {\n uint256 claimedWordIndex = index / 256;\n uint256 claimedBitIndex = index % 256;\n claimedBitMap[claimedWordIndex] = claimedBitMap[claimedWordIndex] | (1 << claimedBitIndex);\n }\n\n function claim(\n uint256 index,\n address account,\n uint256 amount,\n bytes32[] calldata merkleProof\n ) external override {\n require(!isClaimed(index), \"MerkleDistributor: Drop already claimed.\");\n\n // Verify the merkle proof.\n bytes32 node = keccak256(abi.encodePacked(index, account, amount));\n require(\n MerkleProof.verify(merkleProof, merkleRoot, node),\n \"MerkleDistributor: Invalid proof.\"\n );\n\n // Mark it claimed and send the token.\n _setClaimed(index);\n require(IERC20(token).transfer(account, amount), \"MerkleDistributor: Transfer failed.\");\n\n emit Claimed(index, account, amount);\n }\n\n /**\n * @dev Finalises the airdrop and sweeps unclaimed tokens into the Optimism multisig\n */\n function clawBack() external {\n // Airdrop can only be finalised once\n require(isActive, \"Airdrop: Already finalised\");\n // Airdrop will remain open for one year\n require(\n block.timestamp >= activationTimestamp + ONE_YEAR_IN_SECONDS,\n \"Airdrop: Drop should remain open for one year\"\n );\n // Deactivate airdrop\n isActive = false;\n\n // Sweep unclaimed tokens\n uint256 amount = IERC20(token).balanceOf(address(this));\n require(\n IERC20(token).transfer(airdropTreasury, amount),\n \"Airdrop: Finalise transfer failed\"\n );\n\n emit Finalised(msg.sender, block.timestamp, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "contracts/interfaces/IMerkleDistributor.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.12;\n\n// Allows anyone to claim a token if they exist in a merkle root.\ninterface IMerkleDistributor {\n // Returns the address of the token distributed by this contract.\n function token() external view returns (address);\n\n // Returns the merkle root of the merkle tree containing account balances available to claim.\n function merkleRoot() external view returns (bytes32);\n\n // Returns true if the index has been marked claimed.\n function isClaimed(uint256 index) external view returns (bool);\n\n // Claim the given amount of the token to the given address. Reverts if the inputs are invalid.\n function claim(\n uint256 index,\n address account,\n uint256 amount,\n bytes32[] calldata merkleProof\n ) external;\n\n // This event is triggered whenever a call to #claim succeeds.\n event Claimed(uint256 index, address account, uint256 amount);\n}\n" + } + }, + "settings": { + "outputSelection": { + "*": { + "*": [ + "metadata", + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/contracts-governance/deployments/optimism-mainnet/.chainId b/packages/contracts-governance/deployments/optimism-mainnet/.chainId new file mode 100644 index 0000000000000..9a037142aa3c1 --- /dev/null +++ b/packages/contracts-governance/deployments/optimism-mainnet/.chainId @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/packages/contracts-governance/deployments/optimism-mainnet/MintManager.json b/packages/contracts-governance/deployments/optimism-mainnet/MintManager.json new file mode 100644 index 0000000000000..f71c767af6189 --- /dev/null +++ b/packages/contracts-governance/deployments/optimism-mainnet/MintManager.json @@ -0,0 +1,316 @@ +{ + "address": "0x5C4e7Ba1E219E47948e6e3F55019A647bA501005", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_upgrader", + "type": "address" + }, + { + "internalType": "address", + "name": "_governanceToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINT_CAP", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINT_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governanceToken", + "outputs": [ + { + "internalType": "contract GovernanceToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintPermittedAfter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newMintManager", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x87f4ef2d91434e18615cabd129752c1f50600a7152f036828e8667b32c10bb1a", + "receipt": { + "to": null, + "from": "0x4D014f3c5F33Aa9Cd1Dc29ce29618d07Ae666d15", + "contractAddress": "0x5C4e7Ba1E219E47948e6e3F55019A647bA501005", + "transactionIndex": 0, + "gasUsed": "880798", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000200020000000000000000000000000000000000000000000000000000000000000000000000000000004000001000000000000000000000000000140000000020000000000000020000800000000000000000000000000000000400000000000000000000000000000000010000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x87432e6b30f06243ca328c59d522b3a361bb863726e1e8e171e607d49bb7df66", + "transactionHash": "0x87f4ef2d91434e18615cabd129752c1f50600a7152f036828e8667b32c10bb1a", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 28103702, + "transactionHash": "0x87f4ef2d91434e18615cabd129752c1f50600a7152f036828e8667b32c10bb1a", + "address": "0x5C4e7Ba1E219E47948e6e3F55019A647bA501005", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004d014f3c5f33aa9cd1dc29ce29618d07ae666d15" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x87432e6b30f06243ca328c59d522b3a361bb863726e1e8e171e607d49bb7df66" + }, + { + "transactionIndex": 0, + "blockNumber": 28103702, + "transactionHash": "0x87f4ef2d91434e18615cabd129752c1f50600a7152f036828e8667b32c10bb1a", + "address": "0x5C4e7Ba1E219E47948e6e3F55019A647bA501005", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000004d014f3c5f33aa9cd1dc29ce29618d07ae666d15", + "0x0000000000000000000000002a82ae142b2e62cb7d10b55e323acb1cab663a26" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x87432e6b30f06243ca328c59d522b3a361bb863726e1e8e171e607d49bb7df66" + } + ], + "blockNumber": 28103702, + "cumulativeGasUsed": "880798", + "status": 1, + "byzantium": true + }, + "args": [ + "0x2A82Ae142b2e62Cb7D10b55E323ACB1Cab663a26", + "0x4200000000000000000000000000000000000042" + ], + "numDeployments": 1, + "solcInputHash": "b1df373a9ed51b3903b61f56faa9a78f", + "metadata": "{\"compiler\":{\"version\":\"0.8.12+commit.f00d7308\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_upgrader\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_governanceToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINT_CAP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINT_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governanceToken\",\"outputs\":[{\"internalType\":\"contract GovernanceToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintPermittedAfter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newMintManager\",\"type\":\"address\"}],\"name\":\"upgrade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_governanceToken\":\"The governance token this contract can mint tokens of\",\"_upgrader\":\"The owner of this contract\"}},\"mint(address,uint256)\":{\"params\":{\"_account\":\"Address to mint new tokens to.\",\"_amount\":\"Amount of tokens to be minted.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address)\":{\"params\":{\"_newMintManager\":\"The MintManager to upgrade to\"}}},\"title\":\"MintManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DENOMINATOR()\":{\"notice\":\"The number of decimals for the MINT_CAP.\"},\"MINT_CAP()\":{\"notice\":\"The amount of tokens that can be minted per year. The value is a fixed point number with 4 decimals.\"},\"MINT_PERIOD()\":{\"notice\":\"The amount of time that must pass before the MINT_CAP number of tokens can be minted again.\"},\"governanceToken()\":{\"notice\":\"The GovernanceToken that the MintManager can mint tokens\"},\"mint(address,uint256)\":{\"notice\":\"Only the token owner is allowed to mint a certain amount of OP per year.\"},\"mintPermittedAfter()\":{\"notice\":\"Tracks the time of last mint\"},\"upgrade(address)\":{\"notice\":\"Upgrade the owner of the governance token to a new MintManager.\"}},\"notice\":\"Set as `owner` of the OP token and responsible for the token inflation schedule. Contract acts as the token \\\"mint manager\\\" with permission to the `mint` function only. Currently permitted to mint once per year of up to 2% of the total token supply. Upgradable to allow changes in the inflation schedule.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/MintManager.sol\":\"MintManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(\\n address delegatee,\\n uint256 nonce,\\n uint256 expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0xf5324a55ee9c0b4a840ea57c055ac9d046f88986ceef567e1cf68113e46a79c0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, _allowances[owner][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = _allowances[owner][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n }\\n _balances[to] += amount;\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Spend `amount` form the allowance of `owner` toward `spender`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0xdadd41acb749920eccf40aeaa8d291adf9751399a7343561bad13e7a8d99be0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xbbc8ac883ac3c0078ce5ad3e288fbb3ffcc8a30c3a98c0fda0114d64fc44fca2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n _spendAllowance(account, _msgSender(), amount);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x0d19410453cda55960a818e02bd7c18952a5c8fe7a3036e81f0d599f34487a7b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./draft-ERC20Permit.sol\\\";\\nimport \\\"../../../utils/math/Math.sol\\\";\\nimport \\\"../../../governance/utils/IVotes.sol\\\";\\nimport \\\"../../../utils/math/SafeCast.sol\\\";\\nimport \\\"../../../utils/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,\\n * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.\\n *\\n * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.\\n *\\n * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either\\n * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting\\n * power can be queried through the public accessors {getVotes} and {getPastVotes}.\\n *\\n * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it\\n * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.\\n *\\n * _Available since v4.2._\\n */\\nabstract contract ERC20Votes is IVotes, ERC20Permit {\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint224 votes;\\n }\\n\\n bytes32 private constant _DELEGATION_TYPEHASH =\\n keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n mapping(address => address) private _delegates;\\n mapping(address => Checkpoint[]) private _checkpoints;\\n Checkpoint[] private _totalSupplyCheckpoints;\\n\\n /**\\n * @dev Get the `pos`-th checkpoint for `account`.\\n */\\n function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {\\n return _checkpoints[account][pos];\\n }\\n\\n /**\\n * @dev Get number of checkpoints for `account`.\\n */\\n function numCheckpoints(address account) public view virtual returns (uint32) {\\n return SafeCast.toUint32(_checkpoints[account].length);\\n }\\n\\n /**\\n * @dev Get the address `account` is currently delegating to.\\n */\\n function delegates(address account) public view virtual override returns (address) {\\n return _delegates[account];\\n }\\n\\n /**\\n * @dev Gets the current votes balance for `account`\\n */\\n function getVotes(address account) public view virtual override returns (uint256) {\\n uint256 pos = _checkpoints[account].length;\\n return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;\\n }\\n\\n /**\\n * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.\\n *\\n * Requirements:\\n *\\n * - `blockNumber` must have been already mined\\n */\\n function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {\\n require(blockNumber < block.number, \\\"ERC20Votes: block not yet mined\\\");\\n return _checkpointsLookup(_checkpoints[account], blockNumber);\\n }\\n\\n /**\\n * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.\\n * It is but NOT the sum of all the delegated votes!\\n *\\n * Requirements:\\n *\\n * - `blockNumber` must have been already mined\\n */\\n function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {\\n require(blockNumber < block.number, \\\"ERC20Votes: block not yet mined\\\");\\n return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);\\n }\\n\\n /**\\n * @dev Lookup a value in a list of (sorted) checkpoints.\\n */\\n function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {\\n // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.\\n //\\n // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).\\n // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.\\n // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)\\n // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high)\\n // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not\\n // out of bounds (in which case we're looking too far in the past and the result is 0).\\n // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is\\n // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out\\n // the same.\\n uint256 high = ckpts.length;\\n uint256 low = 0;\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n if (ckpts[mid].fromBlock > blockNumber) {\\n high = mid;\\n } else {\\n low = mid + 1;\\n }\\n }\\n\\n return high == 0 ? 0 : ckpts[high - 1].votes;\\n }\\n\\n /**\\n * @dev Delegate votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) public virtual override {\\n _delegate(_msgSender(), delegatee);\\n }\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`\\n */\\n function delegateBySig(\\n address delegatee,\\n uint256 nonce,\\n uint256 expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override {\\n require(block.timestamp <= expiry, \\\"ERC20Votes: signature expired\\\");\\n address signer = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),\\n v,\\n r,\\n s\\n );\\n require(nonce == _useNonce(signer), \\\"ERC20Votes: invalid nonce\\\");\\n _delegate(signer, delegatee);\\n }\\n\\n /**\\n * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).\\n */\\n function _maxSupply() internal view virtual returns (uint224) {\\n return type(uint224).max;\\n }\\n\\n /**\\n * @dev Snapshots the totalSupply after it has been increased.\\n */\\n function _mint(address account, uint256 amount) internal virtual override {\\n super._mint(account, amount);\\n require(totalSupply() <= _maxSupply(), \\\"ERC20Votes: total supply risks overflowing votes\\\");\\n\\n _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);\\n }\\n\\n /**\\n * @dev Snapshots the totalSupply after it has been decreased.\\n */\\n function _burn(address account, uint256 amount) internal virtual override {\\n super._burn(account, amount);\\n\\n _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);\\n }\\n\\n /**\\n * @dev Move voting power when tokens are transferred.\\n *\\n * Emits a {DelegateVotesChanged} event.\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override {\\n super._afterTokenTransfer(from, to, amount);\\n\\n _moveVotingPower(delegates(from), delegates(to), amount);\\n }\\n\\n /**\\n * @dev Change delegation for `delegator` to `delegatee`.\\n *\\n * Emits events {DelegateChanged} and {DelegateVotesChanged}.\\n */\\n function _delegate(address delegator, address delegatee) internal virtual {\\n address currentDelegate = delegates(delegator);\\n uint256 delegatorBalance = balanceOf(delegator);\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveVotingPower(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _moveVotingPower(\\n address src,\\n address dst,\\n uint256 amount\\n ) private {\\n if (src != dst && amount > 0) {\\n if (src != address(0)) {\\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);\\n emit DelegateVotesChanged(src, oldWeight, newWeight);\\n }\\n\\n if (dst != address(0)) {\\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);\\n emit DelegateVotesChanged(dst, oldWeight, newWeight);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(\\n Checkpoint[] storage ckpts,\\n function(uint256, uint256) view returns (uint256) op,\\n uint256 delta\\n ) private returns (uint256 oldWeight, uint256 newWeight) {\\n uint256 pos = ckpts.length;\\n oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes;\\n newWeight = op(oldWeight, delta);\\n\\n if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {\\n ckpts[pos - 1].votes = SafeCast.toUint224(newWeight);\\n } else {\\n ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)}));\\n }\\n }\\n\\n function _add(uint256 a, uint256 b) private pure returns (uint256) {\\n return a + b;\\n }\\n\\n function _subtract(uint256 a, uint256 b) private pure returns (uint256) {\\n return a - b;\\n }\\n}\\n\",\"keccak256\":\"0x7fd2492be0468be4662081ee25cde38a31e4a0ceca0fed10160462389013910f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-ERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./draft-IERC20Permit.sol\\\";\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"../../../utils/cryptography/ECDSA.sol\\\";\\nimport \\\"../../../utils/Counters.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n *\\n * _Available since v3.4._\\n */\\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\\n using Counters for Counters.Counter;\\n\\n mapping(address => Counters.Counter) private _nonces;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 private immutable _PERMIT_TYPEHASH =\\n keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n\\n /**\\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n *\\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\\n */\\n constructor(string memory name) EIP712(name, \\\"1\\\") {}\\n\\n /**\\n * @dev See {IERC20Permit-permit}.\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override {\\n require(block.timestamp <= deadline, \\\"ERC20Permit: expired deadline\\\");\\n\\n bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\\n\\n bytes32 hash = _hashTypedDataV4(structHash);\\n\\n address signer = ECDSA.recover(hash, v, r, s);\\n require(signer == owner, \\\"ERC20Permit: invalid signature\\\");\\n\\n _approve(owner, spender, value);\\n }\\n\\n /**\\n * @dev See {IERC20Permit-nonces}.\\n */\\n function nonces(address owner) public view virtual override returns (uint256) {\\n return _nonces[owner].current();\\n }\\n\\n /**\\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\\n return _domainSeparatorV4();\\n }\\n\\n /**\\n * @dev \\\"Consume a nonce\\\": return the current value and increment.\\n *\\n * _Available since v4.1._\\n */\\n function _useNonce(address owner) internal virtual returns (uint256 current) {\\n Counters.Counter storage nonce = _nonces[owner];\\n current = nonce.current();\\n nonce.increment();\\n }\\n}\\n\",\"keccak256\":\"0x8a763ef5625e97f5287c7ddd5ede434129069e15d83bf0a68ad10a5e56ccb439\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Counters.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n */\\nlibrary Counters {\\n struct Counter {\\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n // this feature: see https://github.com/ethereum/solidity/issues/4637\\n uint256 _value; // default: 0\\n }\\n\\n function current(Counter storage counter) internal view returns (uint256) {\\n return counter._value;\\n }\\n\\n function increment(Counter storage counter) internal {\\n unchecked {\\n counter._value += 1;\\n }\\n }\\n\\n function decrement(Counter storage counter) internal {\\n uint256 value = counter._value;\\n require(value > 0, \\\"Counter: decrement overflow\\\");\\n unchecked {\\n counter._value = value - 1;\\n }\\n }\\n\\n function reset(Counter storage counter) internal {\\n counter._value = 0;\\n }\\n}\\n\",\"keccak256\":\"0xf0018c2440fbe238dd3a8732fa8e17a0f9dce84d31451dc8a32f6d62b349c9f1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n } else if (error == RecoverError.InvalidSignatureV) {\\n revert(\\\"ECDSA: invalid signature 'v' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n // Check the signature length\\n // - case 65: r,s,v signature (standard)\\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else if (signature.length == 64) {\\n bytes32 r;\\n bytes32 vs;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly {\\n r := mload(add(signature, 0x20))\\n vs := mload(add(signature, 0x40))\\n }\\n return tryRecover(hash, r, vs);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n if (v != 27 && v != 28) {\\n return (address(0), RecoverError.InvalidSignatureV);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x3c07f43e60e099b3b157243b3152722e73b80eeb7985c2cd73712828d7f7da29\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x6688fad58b9ec0286d40fa957152e575d5d8bd4c3aa80985efdb11b44f776ae7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a / b + (a % b == 0 ? 0 : 1);\\n }\\n}\\n\",\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits.\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128) {\\n require(value >= type(int128).min && value <= type(int128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return int128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64) {\\n require(value >= type(int64).min && value <= type(int64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return int64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32) {\\n require(value >= type(int32).min && value <= type(int32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return int32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16) {\\n require(value >= type(int16).min && value <= type(int16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return int16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits.\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8) {\\n require(value >= type(int8).min && value <= type(int8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return int8(value);\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x5c6caab697d302ad7eb59c234a4d2dbc965c1bae87709bd2850060b7695b28c7\",\"license\":\"MIT\"},\"contracts/GovernanceToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * @dev The Optimism token used in governance and supporting voting and delegation.\\n * Implements EIP 2612 allowing signed approvals.\\n * Contract is \\\"owned\\\" by a `MintManager` instance with permission to the `mint` function only,\\n * for the purposes of enforcing the token inflation schedule.\\n */\\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\\n /**\\n * @dev Constructor.\\n */\\n constructor() ERC20(\\\"Optimism\\\", \\\"OP\\\") ERC20Permit(\\\"Optimism\\\") {}\\n\\n function mint(address _account, uint256 _amount) public onlyOwner {\\n _mint(_account, _amount);\\n }\\n\\n // The following functions are overrides required by Solidity.\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal override(ERC20, ERC20Votes) {\\n super._afterTokenTransfer(from, to, amount);\\n }\\n\\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\\n super._mint(to, amount);\\n }\\n\\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\\n super._burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9686248fc10e71c30b05bc86a7b7749f12f74e5701c9d73b15ca9f75b9093839\",\"license\":\"MIT\"},\"contracts/MintManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.12;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"./GovernanceToken.sol\\\";\\n\\n/**\\n * @title MintManager\\n * @notice Set as `owner` of the OP token and responsible for the token inflation schedule.\\n * Contract acts as the token \\\"mint manager\\\" with permission to the `mint` function only.\\n * Currently permitted to mint once per year of up to 2% of the total token supply.\\n * Upgradable to allow changes in the inflation schedule.\\n */\\ncontract MintManager is Ownable {\\n /**\\n * @notice The GovernanceToken that the MintManager can mint tokens\\n */\\n GovernanceToken public immutable governanceToken;\\n\\n /**\\n * @notice The amount of tokens that can be minted per year. The value is a fixed\\n * point number with 4 decimals.\\n */\\n uint256 public constant MINT_CAP = 20; // 2%\\n\\n /**\\n * @notice The number of decimals for the MINT_CAP.\\n */\\n uint256 public constant DENOMINATOR = 1000;\\n\\n /**\\n * @notice The amount of time that must pass before the MINT_CAP number of tokens can\\n * be minted again.\\n */\\n uint256 public constant MINT_PERIOD = 365 days;\\n\\n /**\\n * @notice Tracks the time of last mint\\n */\\n uint256 public mintPermittedAfter;\\n\\n /**\\n * @param _upgrader The owner of this contract\\n * @param _governanceToken The governance token this contract can mint\\n * tokens of\\n */\\n constructor(address _upgrader, address _governanceToken) {\\n transferOwnership(_upgrader);\\n governanceToken = GovernanceToken(_governanceToken);\\n }\\n\\n /**\\n * @notice Only the token owner is allowed to mint a certain amount of OP per year.\\n *\\n * @param _account Address to mint new tokens to.\\n * @param _amount Amount of tokens to be minted.\\n */\\n function mint(address _account, uint256 _amount) public onlyOwner {\\n if (mintPermittedAfter > 0) {\\n require(mintPermittedAfter <= block.timestamp, \\\"OP: minting not permitted yet\\\");\\n\\n require(\\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\\n \\\"OP: mint amount exceeds cap\\\"\\n );\\n }\\n\\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\\n\\n governanceToken.mint(_account, _amount);\\n }\\n\\n /**\\n * @notice Upgrade the owner of the governance token to a new MintManager.\\n *\\n * @param _newMintManager The MintManager to upgrade to\\n */\\n function upgrade(address _newMintManager) public onlyOwner {\\n require(_newMintManager != address(0), \\\"OP: Mint manager cannot be empty\\\");\\n\\n governanceToken.transferOwnership(_newMintManager);\\n }\\n}\\n\",\"keccak256\":\"0x502e1e705839a9840823fe4c2eef2cf7f717b548c2259c6c5cf5e62753fbd940\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b50604051620012f1380380620012f1833981810160405281019062000037919062000319565b620000576200004b620000a460201b60201c565b620000ac60201b60201c565b62000068826200017060201b60201c565b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505050506200047b565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b62000180620000a460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620001a66200028660201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620001ff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001f690620003c1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000272576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002699062000459565b60405180910390fd5b6200028381620000ac60201b60201c565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620002e182620002b4565b9050919050565b620002f381620002d4565b8114620002ff57600080fd5b50565b6000815190506200031381620002e8565b92915050565b60008060408385031215620003335762000332620002af565b5b6000620003438582860162000302565b9250506020620003568582860162000302565b9150509250929050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000620003a960208362000360565b9150620003b68262000371565b602082019050919050565b60006020820190508181036000830152620003dc816200039a565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006200044160268362000360565b91506200044e82620003e3565b604082019050919050565b60006020820190508181036000830152620004748162000432565b9050919050565b608051610e45620004ac600039600081816102a8015281816104070152818161050301526107500152610e456000f3fe608060405234801561001057600080fd5b506004361061009d5760003560e01c80638da5cb5b116100665780638da5cb5b14610120578063918f86741461013e57806398f1312e1461015c578063f2fde38b1461017a578063f96dae0a146101965761009d565b8062f8900c146100a25780630900f010146100c057806340c10f19146100dc578063715018a6146100f857806383ea6e9714610102575b600080fd5b6100aa6101b4565b6040516100b79190610857565b60405180910390f35b6100da60048036038101906100d591906108d5565b6101ba565b005b6100f660048036038101906100f1919061092e565b610334565b005b610100610592565b005b61010a61061a565b6040516101179190610857565b60405180910390f35b610128610622565b604051610135919061097d565b60405180910390f35b61014661064b565b6040516101539190610857565b60405180910390f35b610164610651565b6040516101719190610857565b60405180910390f35b610194600480360381019061018f91906108d5565b610656565b005b61019e61074e565b6040516101ab91906109f7565b60405180910390f35b60015481565b6101c2610772565b73ffffffffffffffffffffffffffffffffffffffff166101e0610622565b73ffffffffffffffffffffffffffffffffffffffff1614610236576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022d90610a6f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156102a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161029d90610adb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f2fde38b826040518263ffffffff1660e01b81526004016102ff919061097d565b600060405180830381600087803b15801561031957600080fd5b505af115801561032d573d6000803e3d6000fd5b5050505050565b61033c610772565b73ffffffffffffffffffffffffffffffffffffffff1661035a610622565b73ffffffffffffffffffffffffffffffffffffffff16146103b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a790610a6f565b60405180910390fd5b600060015411156104eb57426001541115610400576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f790610b47565b60405180910390fd5b6103e860147f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610470573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104949190610b7c565b61049e9190610bd8565b6104a89190610c61565b8111156104ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e190610cde565b60405180910390fd5b5b6301e13380426104fb9190610cfe565b6001819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166340c10f1983836040518363ffffffff1660e01b815260040161055c929190610d54565b600060405180830381600087803b15801561057657600080fd5b505af115801561058a573d6000803e3d6000fd5b505050505050565b61059a610772565b73ffffffffffffffffffffffffffffffffffffffff166105b8610622565b73ffffffffffffffffffffffffffffffffffffffff161461060e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060590610a6f565b60405180910390fd5b610618600061077a565b565b6301e1338081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6103e881565b601481565b61065e610772565b73ffffffffffffffffffffffffffffffffffffffff1661067c610622565b73ffffffffffffffffffffffffffffffffffffffff16146106d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c990610a6f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073990610def565b60405180910390fd5b61074b8161077a565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b6108518161083e565b82525050565b600060208201905061086c6000830184610848565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006108a282610877565b9050919050565b6108b281610897565b81146108bd57600080fd5b50565b6000813590506108cf816108a9565b92915050565b6000602082840312156108eb576108ea610872565b5b60006108f9848285016108c0565b91505092915050565b61090b8161083e565b811461091657600080fd5b50565b60008135905061092881610902565b92915050565b6000806040838503121561094557610944610872565b5b6000610953858286016108c0565b925050602061096485828601610919565b9150509250929050565b61097781610897565b82525050565b6000602082019050610992600083018461096e565b92915050565b6000819050919050565b60006109bd6109b86109b384610877565b610998565b610877565b9050919050565b60006109cf826109a2565b9050919050565b60006109e1826109c4565b9050919050565b6109f1816109d6565b82525050565b6000602082019050610a0c60008301846109e8565b92915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610a59602083610a12565b9150610a6482610a23565b602082019050919050565b60006020820190508181036000830152610a8881610a4c565b9050919050565b7f4f503a204d696e74206d616e616765722063616e6e6f7420626520656d707479600082015250565b6000610ac5602083610a12565b9150610ad082610a8f565b602082019050919050565b60006020820190508181036000830152610af481610ab8565b9050919050565b7f4f503a206d696e74696e67206e6f74207065726d697474656420796574000000600082015250565b6000610b31601d83610a12565b9150610b3c82610afb565b602082019050919050565b60006020820190508181036000830152610b6081610b24565b9050919050565b600081519050610b7681610902565b92915050565b600060208284031215610b9257610b91610872565b5b6000610ba084828501610b67565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610be38261083e565b9150610bee8361083e565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610c2757610c26610ba9565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000610c6c8261083e565b9150610c778361083e565b925082610c8757610c86610c32565b5b828204905092915050565b7f4f503a206d696e7420616d6f756e742065786365656473206361700000000000600082015250565b6000610cc8601b83610a12565b9150610cd382610c92565b602082019050919050565b60006020820190508181036000830152610cf781610cbb565b9050919050565b6000610d098261083e565b9150610d148361083e565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610d4957610d48610ba9565b5b828201905092915050565b6000604082019050610d69600083018561096e565b610d766020830184610848565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610dd9602683610a12565b9150610de482610d7d565b604082019050919050565b60006020820190508181036000830152610e0881610dcc565b905091905056fea2646970667358221220d6ef0f15f2581f08c298ff8c67408d75a27f67742459525e88193c029a7a0bcf64736f6c634300080c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061009d5760003560e01c80638da5cb5b116100665780638da5cb5b14610120578063918f86741461013e57806398f1312e1461015c578063f2fde38b1461017a578063f96dae0a146101965761009d565b8062f8900c146100a25780630900f010146100c057806340c10f19146100dc578063715018a6146100f857806383ea6e9714610102575b600080fd5b6100aa6101b4565b6040516100b79190610857565b60405180910390f35b6100da60048036038101906100d591906108d5565b6101ba565b005b6100f660048036038101906100f1919061092e565b610334565b005b610100610592565b005b61010a61061a565b6040516101179190610857565b60405180910390f35b610128610622565b604051610135919061097d565b60405180910390f35b61014661064b565b6040516101539190610857565b60405180910390f35b610164610651565b6040516101719190610857565b60405180910390f35b610194600480360381019061018f91906108d5565b610656565b005b61019e61074e565b6040516101ab91906109f7565b60405180910390f35b60015481565b6101c2610772565b73ffffffffffffffffffffffffffffffffffffffff166101e0610622565b73ffffffffffffffffffffffffffffffffffffffff1614610236576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022d90610a6f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156102a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161029d90610adb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f2fde38b826040518263ffffffff1660e01b81526004016102ff919061097d565b600060405180830381600087803b15801561031957600080fd5b505af115801561032d573d6000803e3d6000fd5b5050505050565b61033c610772565b73ffffffffffffffffffffffffffffffffffffffff1661035a610622565b73ffffffffffffffffffffffffffffffffffffffff16146103b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a790610a6f565b60405180910390fd5b600060015411156104eb57426001541115610400576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f790610b47565b60405180910390fd5b6103e860147f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610470573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104949190610b7c565b61049e9190610bd8565b6104a89190610c61565b8111156104ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e190610cde565b60405180910390fd5b5b6301e13380426104fb9190610cfe565b6001819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166340c10f1983836040518363ffffffff1660e01b815260040161055c929190610d54565b600060405180830381600087803b15801561057657600080fd5b505af115801561058a573d6000803e3d6000fd5b505050505050565b61059a610772565b73ffffffffffffffffffffffffffffffffffffffff166105b8610622565b73ffffffffffffffffffffffffffffffffffffffff161461060e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060590610a6f565b60405180910390fd5b610618600061077a565b565b6301e1338081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6103e881565b601481565b61065e610772565b73ffffffffffffffffffffffffffffffffffffffff1661067c610622565b73ffffffffffffffffffffffffffffffffffffffff16146106d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c990610a6f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073990610def565b60405180910390fd5b61074b8161077a565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b6108518161083e565b82525050565b600060208201905061086c6000830184610848565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006108a282610877565b9050919050565b6108b281610897565b81146108bd57600080fd5b50565b6000813590506108cf816108a9565b92915050565b6000602082840312156108eb576108ea610872565b5b60006108f9848285016108c0565b91505092915050565b61090b8161083e565b811461091657600080fd5b50565b60008135905061092881610902565b92915050565b6000806040838503121561094557610944610872565b5b6000610953858286016108c0565b925050602061096485828601610919565b9150509250929050565b61097781610897565b82525050565b6000602082019050610992600083018461096e565b92915050565b6000819050919050565b60006109bd6109b86109b384610877565b610998565b610877565b9050919050565b60006109cf826109a2565b9050919050565b60006109e1826109c4565b9050919050565b6109f1816109d6565b82525050565b6000602082019050610a0c60008301846109e8565b92915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610a59602083610a12565b9150610a6482610a23565b602082019050919050565b60006020820190508181036000830152610a8881610a4c565b9050919050565b7f4f503a204d696e74206d616e616765722063616e6e6f7420626520656d707479600082015250565b6000610ac5602083610a12565b9150610ad082610a8f565b602082019050919050565b60006020820190508181036000830152610af481610ab8565b9050919050565b7f4f503a206d696e74696e67206e6f74207065726d697474656420796574000000600082015250565b6000610b31601d83610a12565b9150610b3c82610afb565b602082019050919050565b60006020820190508181036000830152610b6081610b24565b9050919050565b600081519050610b7681610902565b92915050565b600060208284031215610b9257610b91610872565b5b6000610ba084828501610b67565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610be38261083e565b9150610bee8361083e565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610c2757610c26610ba9565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000610c6c8261083e565b9150610c778361083e565b925082610c8757610c86610c32565b5b828204905092915050565b7f4f503a206d696e7420616d6f756e742065786365656473206361700000000000600082015250565b6000610cc8601b83610a12565b9150610cd382610c92565b602082019050919050565b60006020820190508181036000830152610cf781610cbb565b9050919050565b6000610d098261083e565b9150610d148361083e565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610d4957610d48610ba9565b5b828201905092915050565b6000604082019050610d69600083018561096e565b610d766020830184610848565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610dd9602683610a12565b9150610de482610d7d565b604082019050919050565b60006020820190508181036000830152610e0881610dcc565b905091905056fea2646970667358221220d6ef0f15f2581f08c298ff8c67408d75a27f67742459525e88193c029a7a0bcf64736f6c634300080c0033", + "devdoc": { + "kind": "dev", + "methods": { + "constructor": { + "params": { + "_governanceToken": "The governance token this contract can mint tokens of", + "_upgrader": "The owner of this contract" + } + }, + "mint(address,uint256)": { + "params": { + "_account": "Address to mint new tokens to.", + "_amount": "Amount of tokens to be minted." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgrade(address)": { + "params": { + "_newMintManager": "The MintManager to upgrade to" + } + } + }, + "title": "MintManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "DENOMINATOR()": { + "notice": "The number of decimals for the MINT_CAP." + }, + "MINT_CAP()": { + "notice": "The amount of tokens that can be minted per year. The value is a fixed point number with 4 decimals." + }, + "MINT_PERIOD()": { + "notice": "The amount of time that must pass before the MINT_CAP number of tokens can be minted again." + }, + "governanceToken()": { + "notice": "The GovernanceToken that the MintManager can mint tokens" + }, + "mint(address,uint256)": { + "notice": "Only the token owner is allowed to mint a certain amount of OP per year." + }, + "mintPermittedAfter()": { + "notice": "Tracks the time of last mint" + }, + "upgrade(address)": { + "notice": "Upgrade the owner of the governance token to a new MintManager." + } + }, + "notice": "Set as `owner` of the OP token and responsible for the token inflation schedule. Contract acts as the token \"mint manager\" with permission to the `mint` function only. Currently permitted to mint once per year of up to 2% of the total token supply. Upgradable to allow changes in the inflation schedule.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/MintManager.sol:MintManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3573, + "contract": "contracts/MintManager.sol:MintManager", + "label": "mintPermittedAfter", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/contracts-governance/deployments/optimism-mainnet/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json b/packages/contracts-governance/deployments/optimism-mainnet/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json new file mode 100644 index 0000000000000..b0bf9b8a4dfb4 --- /dev/null +++ b/packages/contracts-governance/deployments/optimism-mainnet/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "contracts/GovernanceToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @dev The Optimism token used in governance and supporting voting and delegation.\n * Implements EIP 2612 allowing signed approvals.\n * Contract is \"owned\" by a `MintManager` instance with permission to the `mint` function only,\n * for the purposes of enforcing the token inflation schedule.\n */\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\n /**\n * @dev Constructor.\n */\n constructor() ERC20(\"Optimism\", \"OP\") ERC20Permit(\"Optimism\") {}\n\n function mint(address _account, uint256 _amount) public onlyOwner {\n _mint(_account, _amount);\n }\n\n // The following functions are overrides required by Solidity.\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override(ERC20, ERC20Votes) {\n super._afterTokenTransfer(from, to, amount);\n }\n\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, _allowances[owner][spender] + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = _allowances[owner][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Spend `amount` form the allowance of `owner` toward `spender`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./draft-ERC20Permit.sol\";\nimport \"../../../utils/math/Math.sol\";\nimport \"../../../governance/utils/IVotes.sol\";\nimport \"../../../utils/math/SafeCast.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\n\n/**\n * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,\n * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.\n *\n * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.\n *\n * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either\n * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting\n * power can be queried through the public accessors {getVotes} and {getPastVotes}.\n *\n * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it\n * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.\n *\n * _Available since v4.2._\n */\nabstract contract ERC20Votes is IVotes, ERC20Permit {\n struct Checkpoint {\n uint32 fromBlock;\n uint224 votes;\n }\n\n bytes32 private constant _DELEGATION_TYPEHASH =\n keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n mapping(address => address) private _delegates;\n mapping(address => Checkpoint[]) private _checkpoints;\n Checkpoint[] private _totalSupplyCheckpoints;\n\n /**\n * @dev Get the `pos`-th checkpoint for `account`.\n */\n function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {\n return _checkpoints[account][pos];\n }\n\n /**\n * @dev Get number of checkpoints for `account`.\n */\n function numCheckpoints(address account) public view virtual returns (uint32) {\n return SafeCast.toUint32(_checkpoints[account].length);\n }\n\n /**\n * @dev Get the address `account` is currently delegating to.\n */\n function delegates(address account) public view virtual override returns (address) {\n return _delegates[account];\n }\n\n /**\n * @dev Gets the current votes balance for `account`\n */\n function getVotes(address account) public view virtual override returns (uint256) {\n uint256 pos = _checkpoints[account].length;\n return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;\n }\n\n /**\n * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.\n *\n * Requirements:\n *\n * - `blockNumber` must have been already mined\n */\n function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {\n require(blockNumber < block.number, \"ERC20Votes: block not yet mined\");\n return _checkpointsLookup(_checkpoints[account], blockNumber);\n }\n\n /**\n * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.\n * It is but NOT the sum of all the delegated votes!\n *\n * Requirements:\n *\n * - `blockNumber` must have been already mined\n */\n function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {\n require(blockNumber < block.number, \"ERC20Votes: block not yet mined\");\n return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);\n }\n\n /**\n * @dev Lookup a value in a list of (sorted) checkpoints.\n */\n function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {\n // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.\n //\n // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).\n // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.\n // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)\n // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high)\n // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not\n // out of bounds (in which case we're looking too far in the past and the result is 0).\n // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is\n // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out\n // the same.\n uint256 high = ckpts.length;\n uint256 low = 0;\n while (low < high) {\n uint256 mid = Math.average(low, high);\n if (ckpts[mid].fromBlock > blockNumber) {\n high = mid;\n } else {\n low = mid + 1;\n }\n }\n\n return high == 0 ? 0 : ckpts[high - 1].votes;\n }\n\n /**\n * @dev Delegate votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) public virtual override {\n _delegate(_msgSender(), delegatee);\n }\n\n /**\n * @dev Delegates votes from signer to `delegatee`\n */\n function delegateBySig(\n address delegatee,\n uint256 nonce,\n uint256 expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n require(block.timestamp <= expiry, \"ERC20Votes: signature expired\");\n address signer = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),\n v,\n r,\n s\n );\n require(nonce == _useNonce(signer), \"ERC20Votes: invalid nonce\");\n _delegate(signer, delegatee);\n }\n\n /**\n * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).\n */\n function _maxSupply() internal view virtual returns (uint224) {\n return type(uint224).max;\n }\n\n /**\n * @dev Snapshots the totalSupply after it has been increased.\n */\n function _mint(address account, uint256 amount) internal virtual override {\n super._mint(account, amount);\n require(totalSupply() <= _maxSupply(), \"ERC20Votes: total supply risks overflowing votes\");\n\n _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);\n }\n\n /**\n * @dev Snapshots the totalSupply after it has been decreased.\n */\n function _burn(address account, uint256 amount) internal virtual override {\n super._burn(account, amount);\n\n _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);\n }\n\n /**\n * @dev Move voting power when tokens are transferred.\n *\n * Emits a {DelegateVotesChanged} event.\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._afterTokenTransfer(from, to, amount);\n\n _moveVotingPower(delegates(from), delegates(to), amount);\n }\n\n /**\n * @dev Change delegation for `delegator` to `delegatee`.\n *\n * Emits events {DelegateChanged} and {DelegateVotesChanged}.\n */\n function _delegate(address delegator, address delegatee) internal virtual {\n address currentDelegate = delegates(delegator);\n uint256 delegatorBalance = balanceOf(delegator);\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n _moveVotingPower(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _moveVotingPower(\n address src,\n address dst,\n uint256 amount\n ) private {\n if (src != dst && amount > 0) {\n if (src != address(0)) {\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);\n emit DelegateVotesChanged(src, oldWeight, newWeight);\n }\n\n if (dst != address(0)) {\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);\n emit DelegateVotesChanged(dst, oldWeight, newWeight);\n }\n }\n }\n\n function _writeCheckpoint(\n Checkpoint[] storage ckpts,\n function(uint256, uint256) view returns (uint256) op,\n uint256 delta\n ) private returns (uint256 oldWeight, uint256 newWeight) {\n uint256 pos = ckpts.length;\n oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes;\n newWeight = op(oldWeight, delta);\n\n if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {\n ckpts[pos - 1].votes = SafeCast.toUint224(newWeight);\n } else {\n ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)}));\n }\n }\n\n function _add(uint256 a, uint256 b) private pure returns (uint256) {\n return a + b;\n }\n\n function _subtract(uint256 a, uint256 b) private pure returns (uint256) {\n return a - b;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-ERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./draft-IERC20Permit.sol\";\nimport \"../ERC20.sol\";\nimport \"../../../utils/cryptography/draft-EIP712.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\nimport \"../../../utils/Counters.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping(address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) EIP712(name, \"1\") {}\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view virtual override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n\n /**\n * @dev \"Consume a nonce\": return the current value and increment.\n *\n * _Available since v4.1._\n */\n function _useNonce(address owner) internal virtual returns (uint256 current) {\n Counters.Counter storage nonce = _nonces[owner];\n current = nonce.current();\n nonce.increment();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a / b + (a % b == 0 ? 0 : 1);\n }\n}\n" + }, + "@openzeppelin/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(\n address delegatee,\n uint256 nonce,\n uint256 expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128) {\n require(value >= type(int128).min && value <= type(int128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return int128(value);\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64) {\n require(value >= type(int64).min && value <= type(int64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return int64(value);\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32) {\n require(value >= type(int32).min && value <= type(int32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return int32(value);\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16) {\n require(value >= type(int16).min && value <= type(int16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return int16(value);\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8) {\n require(value >= type(int8).min && value <= type(int8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return int8(value);\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 && v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "contracts/MintManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./GovernanceToken.sol\";\n\n/**\n * @title MintManager\n * @notice Set as `owner` of the OP token and responsible for the token inflation schedule.\n * Contract acts as the token \"mint manager\" with permission to the `mint` function only.\n * Currently permitted to mint once per year of up to 2% of the total token supply.\n * Upgradable to allow changes in the inflation schedule.\n */\ncontract MintManager is Ownable {\n /**\n * @notice The GovernanceToken that the MintManager can mint tokens\n */\n GovernanceToken public immutable governanceToken;\n\n /**\n * @notice The amount of tokens that can be minted per year. The value is a fixed\n * point number with 4 decimals.\n */\n uint256 public constant MINT_CAP = 20; // 2%\n\n /**\n * @notice The number of decimals for the MINT_CAP.\n */\n uint256 public constant DENOMINATOR = 1000;\n\n /**\n * @notice The amount of time that must pass before the MINT_CAP number of tokens can\n * be minted again.\n */\n uint256 public constant MINT_PERIOD = 365 days;\n\n /**\n * @notice Tracks the time of last mint\n */\n uint256 public mintPermittedAfter;\n\n /**\n * @param _upgrader The owner of this contract\n * @param _governanceToken The governance token this contract can mint\n * tokens of\n */\n constructor(address _upgrader, address _governanceToken) {\n transferOwnership(_upgrader);\n governanceToken = GovernanceToken(_governanceToken);\n }\n\n /**\n * @notice Only the token owner is allowed to mint a certain amount of OP per year.\n *\n * @param _account Address to mint new tokens to.\n * @param _amount Amount of tokens to be minted.\n */\n function mint(address _account, uint256 _amount) public onlyOwner {\n if (mintPermittedAfter > 0) {\n require(mintPermittedAfter <= block.timestamp, \"OP: minting not permitted yet\");\n\n require(\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\n \"OP: mint amount exceeds cap\"\n );\n }\n\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\n\n governanceToken.mint(_account, _amount);\n }\n\n /**\n * @notice Upgrade the owner of the governance token to a new MintManager.\n *\n * @param _newMintManager The MintManager to upgrade to\n */\n function upgrade(address _newMintManager) public onlyOwner {\n require(_newMintManager != address(0), \"OP: Mint manager cannot be empty\");\n\n governanceToken.transferOwnership(_newMintManager);\n }\n}\n" + }, + "contracts/test/TestERC20.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.8.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n constructor(\n string memory name_,\n string memory symbol_,\n uint256 amountToMint\n ) ERC20(name_, symbol_) {\n setBalance(msg.sender, amountToMint);\n }\n\n // sets the balance of the address\n // this mints/burns the amount depending on the current balance\n function setBalance(address to, uint256 amount) public {\n uint256 old = balanceOf(to);\n if (old < amount) {\n _mint(to, amount - old);\n } else if (old > amount) {\n _burn(to, old - amount);\n }\n }\n}\n" + }, + "contracts/MerkleDistributor.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.8.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"./interfaces/IMerkleDistributor.sol\";\n\ncontract MerkleDistributor is IMerkleDistributor {\n address public immutable override token;\n bytes32 public immutable override merkleRoot;\n\n uint256 public constant ONE_YEAR_IN_SECONDS = 31_536_000;\n uint256 public immutable activationTimestamp;\n address public immutable airdropTreasury;\n bool public isActive;\n\n // This is a packed array of booleans.\n mapping(uint256 => uint256) private claimedBitMap;\n\n event Finalised(address indexed calledBy, uint256 timestamp, uint256 unclaimedAmount);\n\n constructor(\n address token_,\n bytes32 merkleRoot_,\n address _treasury\n ) {\n token = token_;\n merkleRoot = merkleRoot_;\n\n activationTimestamp = block.timestamp;\n isActive = true;\n airdropTreasury = _treasury;\n }\n\n function isClaimed(uint256 index) public view override returns (bool) {\n uint256 claimedWordIndex = index / 256;\n uint256 claimedBitIndex = index % 256;\n uint256 claimedWord = claimedBitMap[claimedWordIndex];\n uint256 mask = (1 << claimedBitIndex);\n return claimedWord & mask == mask;\n }\n\n function _setClaimed(uint256 index) private {\n uint256 claimedWordIndex = index / 256;\n uint256 claimedBitIndex = index % 256;\n claimedBitMap[claimedWordIndex] = claimedBitMap[claimedWordIndex] | (1 << claimedBitIndex);\n }\n\n function claim(\n uint256 index,\n address account,\n uint256 amount,\n bytes32[] calldata merkleProof\n ) external override {\n require(!isClaimed(index), \"MerkleDistributor: Drop already claimed.\");\n\n // Verify the merkle proof.\n bytes32 node = keccak256(abi.encodePacked(index, account, amount));\n require(\n MerkleProof.verify(merkleProof, merkleRoot, node),\n \"MerkleDistributor: Invalid proof.\"\n );\n\n // Mark it claimed and send the token.\n _setClaimed(index);\n require(IERC20(token).transfer(account, amount), \"MerkleDistributor: Transfer failed.\");\n\n emit Claimed(index, account, amount);\n }\n\n /**\n * @dev Finalises the airdrop and sweeps unclaimed tokens into the Optimism multisig\n */\n function clawBack() external {\n // Airdrop can only be finalised once\n require(isActive, \"Airdrop: Already finalised\");\n // Airdrop will remain open for one year\n require(\n block.timestamp >= activationTimestamp + ONE_YEAR_IN_SECONDS,\n \"Airdrop: Drop should remain open for one year\"\n );\n // Deactivate airdrop\n isActive = false;\n\n // Sweep unclaimed tokens\n uint256 amount = IERC20(token).balanceOf(address(this));\n require(\n IERC20(token).transfer(airdropTreasury, amount),\n \"Airdrop: Finalise transfer failed\"\n );\n\n emit Finalised(msg.sender, block.timestamp, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "contracts/interfaces/IMerkleDistributor.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.12;\n\n// Allows anyone to claim a token if they exist in a merkle root.\ninterface IMerkleDistributor {\n // Returns the address of the token distributed by this contract.\n function token() external view returns (address);\n\n // Returns the merkle root of the merkle tree containing account balances available to claim.\n function merkleRoot() external view returns (bytes32);\n\n // Returns true if the index has been marked claimed.\n function isClaimed(uint256 index) external view returns (bool);\n\n // Claim the given amount of the token to the given address. Reverts if the inputs are invalid.\n function claim(\n uint256 index,\n address account,\n uint256 amount,\n bytes32[] calldata merkleProof\n ) external;\n\n // This event is triggered whenever a call to #claim succeeds.\n event Claimed(uint256 index, address account, uint256 amount);\n}\n" + } + }, + "settings": { + "outputSelection": { + "*": { + "*": [ + "metadata", + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/contracts-governance/hardhat.config.ts b/packages/contracts-governance/hardhat.config.ts index 89da0d44e8012..252b702871c9a 100644 --- a/packages/contracts-governance/hardhat.config.ts +++ b/packages/contracts-governance/hardhat.config.ts @@ -1,10 +1,13 @@ import dotenv from 'dotenv' import { HardhatUserConfig } from 'hardhat/config' +import { getenv } from '@eth-optimism/core-utils' import '@nomiclabs/hardhat-ethers' import '@nomiclabs/hardhat-etherscan' import '@nomiclabs/hardhat-waffle' import 'hardhat-gas-reporter' import 'solidity-coverage' +import '@eth-optimism/hardhat-deploy-config' +import 'hardhat-deploy' import './scripts/deploy-token' import './scripts/multi-send' @@ -60,6 +63,14 @@ const config: HardhatUserConfig = { url: 'http://localhost:8545', }, }, + paths: { + deployConfig: 'deploy-config', + }, + deployConfigSpec: { + upgrader: { + type: 'address', + }, + }, gasReporter: { enabled: process.env.REPORT_GAS !== undefined, currency: 'USD', @@ -67,6 +78,14 @@ const config: HardhatUserConfig = { etherscan: { apiKey: process.env.ETHERSCAN_API_KEY, }, + namedAccounts: { + deployer: { + default: getenv('LEDGER_ADDRESS') + ? `ledger://${getenv('LEDGER_ADDRESS')}` + : 0, + hardhat: 0, + }, + }, } export default config diff --git a/packages/contracts-governance/package.json b/packages/contracts-governance/package.json index 8e3df228eccf6..bbd5086f69ba9 100644 --- a/packages/contracts-governance/package.json +++ b/packages/contracts-governance/package.json @@ -30,6 +30,7 @@ "dependencies": { "@eth-optimism/core-utils": "^0.10.1", "@eth-optimism/sdk": "^1.6.4", + "@eth-optimism/hardhat-deploy-config": "^0.2.3", "@ethersproject/hardware-wallets": "^5.7.0", "@nomiclabs/hardhat-ethers": "^2.0.2", "@nomiclabs/hardhat-etherscan": "^3.0.1", @@ -50,6 +51,7 @@ "eslint": "^8.9.0", "ethereum-waffle": "^3.4.0", "hardhat-gas-reporter": "^1.0.7", + "hardhat-deploy": "^0.11.4", "prettier": "^2.3.1", "prettier-plugin-solidity": "^1.0.0-beta.18", "solhint": "^3.3.6", diff --git a/packages/contracts-periphery/contracts/universal/op-erc721/OptimismMintableERC721Factory.sol b/packages/contracts-periphery/contracts/universal/op-erc721/OptimismMintableERC721Factory.sol index 6a35401d5440e..670fa76b31b1d 100644 --- a/packages/contracts-periphery/contracts/universal/op-erc721/OptimismMintableERC721Factory.sol +++ b/packages/contracts-periphery/contracts/universal/op-erc721/OptimismMintableERC721Factory.sol @@ -14,8 +14,13 @@ contract OptimismMintableERC721Factory is Semver { * * @param localToken Address of the token on the this domain. * @param remoteToken Address of the token on the remote domain. + * @param deployer Address of the initiator of the deployment */ - event OptimismMintableERC721Created(address indexed localToken, address indexed remoteToken); + event OptimismMintableERC721Created( + address indexed localToken, + address indexed remoteToken, + address deployer + ); /** * @notice Address of the ERC721 bridge on this network. @@ -30,7 +35,7 @@ contract OptimismMintableERC721Factory is Semver { /** * @notice Tracks addresses created by this factory. */ - mapping(address => bool) public isStandardOptimismMintableERC721; + mapping(address => bool) public isOptimismMintableERC721; /** * @custom:semver 1.0.0 @@ -58,25 +63,23 @@ contract OptimismMintableERC721Factory is Semver { * @param _name ERC721 name. * @param _symbol ERC721 symbol. */ - function createStandardOptimismMintableERC721( + function createOptimismMintableERC721( address _remoteToken, string memory _name, string memory _symbol - ) external { + ) external returns (address) { require( _remoteToken != address(0), "OptimismMintableERC721Factory: L1 token address cannot be address(0)" ); - OptimismMintableERC721 localToken = new OptimismMintableERC721( - bridge, - remoteChainId, - _remoteToken, - _name, - _symbol + address localToken = address( + new OptimismMintableERC721(bridge, remoteChainId, _remoteToken, _name, _symbol) ); - isStandardOptimismMintableERC721[address(localToken)] = true; - emit OptimismMintableERC721Created(address(localToken), _remoteToken); + isOptimismMintableERC721[localToken] = true; + emit OptimismMintableERC721Created(localToken, _remoteToken, msg.sender); + + return localToken; } } diff --git a/packages/contracts-periphery/deploy/nft-bridge/L2ERC721BridgeImplementation.ts b/packages/contracts-periphery/deploy/nft-bridge/L2ERC721BridgeImplementation.ts index e5bc678492be3..63e6859aa6c22 100644 --- a/packages/contracts-periphery/deploy/nft-bridge/L2ERC721BridgeImplementation.ts +++ b/packages/contracts-periphery/deploy/nft-bridge/L2ERC721BridgeImplementation.ts @@ -37,9 +37,9 @@ const deployFn: DeployFunction = async (hre) => { throw new Error(`Unexpected admin ${admin}`) } - const Deployment__L1ERC721Bridge = await hre.deployments.get( - 'L1ERC721BridgeProxy' - ) + const Deployment__L1ERC721Bridge = await hre.companionNetworks[ + 'l1' + ].deployments.get('L1ERC721BridgeProxy') const L1ERC721BridgeAddress = Deployment__L1ERC721Bridge.address diff --git a/packages/contracts-periphery/deploy/nft-bridge/L2ERC721BridgeProxy.ts b/packages/contracts-periphery/deploy/nft-bridge/L2ERC721BridgeProxy.ts index 1f494b099d654..b3e6fc8e9f6bd 100644 --- a/packages/contracts-periphery/deploy/nft-bridge/L2ERC721BridgeProxy.ts +++ b/packages/contracts-periphery/deploy/nft-bridge/L2ERC721BridgeProxy.ts @@ -27,6 +27,7 @@ const deployFn: DeployFunction = async (hre) => { const goerliDeployer = getAddress( '0x5c679a57e018f5f146838138d3e032ef4913d551' ) + const kovanDeployer = getAddress('0xa81224490b9fa4930a2e920550cd1c9106bb6d9e') const localDeployer = getAddress('0xdfc82d475833a50de90c642770f34a9db7deb725') // Deploy the L2ERC721BridgeProxy as a predeploy address @@ -42,6 +43,10 @@ const deployFn: DeployFunction = async (hre) => { if (getAddress(deployer) !== localDeployer) { throw new Error(`Incorrect deployer: ${deployer}`) } + } else if (hre.network.name === 'optimism-kovan') { + if (getAddress(deployer) !== kovanDeployer) { + throw new Error(`Incorrect deployer: ${deployer}`) + } } else { throw new Error(`Unknown network: ${hre.network.name}`) } diff --git a/packages/contracts-periphery/deploy/nft-bridge/OptimismMintableERC721FactoryImplementation.ts b/packages/contracts-periphery/deploy/nft-bridge/OptimismMintableERC721FactoryImplementation.ts index cc57d3229f75f..8666a2c96138c 100644 --- a/packages/contracts-periphery/deploy/nft-bridge/OptimismMintableERC721FactoryImplementation.ts +++ b/packages/contracts-periphery/deploy/nft-bridge/OptimismMintableERC721FactoryImplementation.ts @@ -36,6 +36,8 @@ const deployFn: DeployFunction = async (hre) => { remoteChainId = 5 } else if (hre.network.name === 'ops-l2') { remoteChainId = 31337 + } else if (hre.network.name === 'optimism-kovan') { + remoteChainId = 42 } else { remoteChainId = hre.deployConfig.remoteChainId } diff --git a/packages/contracts-periphery/deployments/ethereum/L1ERC721Bridge.json b/packages/contracts-periphery/deployments/ethereum/L1ERC721Bridge.json new file mode 100644 index 0000000000000..e717c3ff5e671 --- /dev/null +++ b/packages/contracts-periphery/deployments/ethereum/L1ERC721Bridge.json @@ -0,0 +1,457 @@ +{ + "address": "0x3268Ed09f76e619331528270B6267D4d2C5Ab5C2", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_messenger", + "type": "address" + }, + { + "internalType": "address", + "name": "_otherBridge", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC721BridgeFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC721BridgeInitiated", + "type": "event" + }, + { + "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" + } + ], + "name": "bridgeERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "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" + } + ], + "name": "bridgeERC721To", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "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" + } + ], + "name": "finalizeBridgeERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "messenger", + "outputs": [ + { + "internalType": "contract CrossDomainMessenger", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "otherBridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x1240d760a2e913292c42a5a662736efa428537ca5eceeef9684bbe8e7f7d89a5", + "receipt": { + "to": null, + "from": "0x53A6eecC2dD4795Fcc68940ddc6B4d53Bd88Bd9E", + "contractAddress": "0x3268Ed09f76e619331528270B6267D4d2C5Ab5C2", + "transactionIndex": 51, + "gasUsed": "1101007", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x0e969f9662b13801e1088e898fc2cf38713c5a8ecab3761d89e3bdbe65e9c16e", + "transactionHash": "0x1240d760a2e913292c42a5a662736efa428537ca5eceeef9684bbe8e7f7d89a5", + "logs": [], + "blockNumber": 15677500, + "cumulativeGasUsed": "4735754", + "status": 1, + "byzantium": true + }, + "args": [ + "0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1", + "0x4200000000000000000000000000000000000014" + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeInitiated\",\"type\":\"event\"},{\"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\"}],\"name\":\"bridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}],\"name\":\"bridgeERC721To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"finalizeBridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"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\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\",\"_otherBridge\":\"Address of the ERC721 bridge on the other 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.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"L1ERC721Bridge\",\"version\":1},\"userdoc\":{\"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.\"}},\"kind\":\"user\",\"methods\":{\"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.\"},\"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.\"},\"messenger()\":{\"notice\":\"Messenger contract on this domain.\"},\"otherBridge()\":{\"notice\":\"Address of the bridge on the other network.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"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.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1/L1ERC721Bridge.sol\":\"L1ERC721Bridge\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { Types } from \\\"./Types.sol\\\";\\nimport { Hashing } from \\\"./Hashing.sol\\\";\\nimport { RLPWriter } from \\\"./rlp/RLPWriter.sol\\\";\\n\\n/**\\n * @title Encoding\\n * @notice Encoding handles Optimism's various different encoding schemes.\\n */\\nlibrary Encoding {\\n /**\\n * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\\n * to the L2 system. Useful for searching for a deposit in the L2 system. The\\n * transaction is prefixed with 0x7e to identify its EIP-2718 type.\\n *\\n * @param _tx User deposit transaction to encode.\\n *\\n * @return RLP encoded L2 deposit transaction.\\n */\\n function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\\n internal\\n pure\\n returns (bytes memory)\\n {\\n bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\\n bytes[] memory raw = new bytes[](8);\\n raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\\n raw[1] = RLPWriter.writeAddress(_tx.from);\\n raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\\\"\\\") : RLPWriter.writeAddress(_tx.to);\\n raw[3] = RLPWriter.writeUint(_tx.mint);\\n raw[4] = RLPWriter.writeUint(_tx.value);\\n raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\\n raw[6] = RLPWriter.writeBool(false);\\n raw[7] = RLPWriter.writeBytes(_tx.data);\\n return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\\n }\\n\\n /**\\n * @notice Encodes the cross domain message based on the version that is encoded into the\\n * message nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes memory) {\\n (, uint16 version) = decodeVersionedNonce(_nonce);\\n if (version == 0) {\\n return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\\n } else if (version == 1) {\\n return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\\n } else {\\n revert(\\\"Encoding: unknown cross domain message version\\\");\\n }\\n }\\n\\n /**\\n * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\\n *\\n * @param _target Address of the target of the message.\\n * @param _sender Address of the sender of the message.\\n * @param _data Data to send with the message.\\n * @param _nonce Message nonce.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessageV0(\\n address _target,\\n address _sender,\\n bytes memory _data,\\n uint256 _nonce\\n ) internal pure returns (bytes memory) {\\n return\\n abi.encodeWithSignature(\\n \\\"relayMessage(address,address,bytes,uint256)\\\",\\n _target,\\n _sender,\\n _data,\\n _nonce\\n );\\n }\\n\\n /**\\n * @notice Encodes a cross domain message based on the V1 (current) encoding.\\n *\\n * @param _nonce Message nonce.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessageV1(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes memory) {\\n return\\n abi.encodeWithSignature(\\n \\\"relayMessage(uint256,address,address,uint256,uint256,bytes)\\\",\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _gasLimit,\\n _data\\n );\\n }\\n\\n /**\\n * @notice Adds a version number into the first two bytes of a message nonce.\\n *\\n * @param _nonce Message nonce to encode into.\\n * @param _version Version number to encode into the message nonce.\\n *\\n * @return Message nonce with version encoded into the first two bytes.\\n */\\n function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\\n uint256 nonce;\\n assembly {\\n nonce := or(shl(240, _version), _nonce)\\n }\\n return nonce;\\n }\\n\\n /**\\n * @notice Pulls the version out of a version-encoded nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n *\\n * @return Nonce without encoded version.\\n * @return Version of the message.\\n */\\n function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\\n uint240 nonce;\\n uint16 version;\\n assembly {\\n nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\\n version := shr(240, _nonce)\\n }\\n return (nonce, version);\\n }\\n}\\n\",\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { Types } from \\\"./Types.sol\\\";\\nimport { Encoding } from \\\"./Encoding.sol\\\";\\n\\n/**\\n * @title Hashing\\n * @notice Hashing handles Optimism's various different hashing schemes.\\n */\\nlibrary Hashing {\\n /**\\n * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\\n * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\\n * system.\\n *\\n * @param _tx User deposit transaction to hash.\\n *\\n * @return Hash of the RLP encoded L2 deposit transaction.\\n */\\n function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return keccak256(Encoding.encodeDepositTransaction(_tx));\\n }\\n\\n /**\\n * @notice Computes the deposit transaction's \\\"source hash\\\", a value that guarantees the hash\\n * of the L2 transaction that corresponds to a deposit is unique and is\\n * deterministically generated from L1 transaction data.\\n *\\n * @param _l1BlockHash Hash of the L1 block where the deposit was included.\\n * @param _logIndex The index of the log that created the deposit transaction.\\n *\\n * @return Hash of the deposit transaction's \\\"source hash\\\".\\n */\\n function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\\n internal\\n pure\\n returns (bytes32)\\n {\\n bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\\n return keccak256(abi.encode(bytes32(0), depositId));\\n }\\n\\n /**\\n * @notice Hashes the cross domain message based on the version that is encoded into the\\n * message nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes32) {\\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\\n if (version == 0) {\\n return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\\n } else if (version == 1) {\\n return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\\n } else {\\n revert(\\\"Hashing: unknown cross domain message version\\\");\\n }\\n }\\n\\n /**\\n * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\\n *\\n * @param _target Address of the target of the message.\\n * @param _sender Address of the sender of the message.\\n * @param _data Data to send with the message.\\n * @param _nonce Message nonce.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessageV0(\\n address _target,\\n address _sender,\\n bytes memory _data,\\n uint256 _nonce\\n ) internal pure returns (bytes32) {\\n return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\\n }\\n\\n /**\\n * @notice Hashes a cross domain message based on the V1 (current) encoding.\\n *\\n * @param _nonce Message nonce.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessageV1(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes32) {\\n return\\n keccak256(\\n Encoding.encodeCrossDomainMessageV1(\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _gasLimit,\\n _data\\n )\\n );\\n }\\n\\n /**\\n * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\\n *\\n * @param _tx Withdrawal transaction to hash.\\n *\\n * @return Hashed withdrawal transaction.\\n */\\n function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\\n );\\n }\\n\\n /**\\n * @notice Hashes the various elements of an output root proof into an output root hash which\\n * can be used to check if the proof is valid.\\n *\\n * @param _outputRootProof Output root proof which should hash to an output root.\\n *\\n * @return Hashed output root proof.\\n */\\n function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encode(\\n _outputRootProof.version,\\n _outputRootProof.stateRoot,\\n _outputRootProof.messagePasserStorageRoot,\\n _outputRootProof.latestBlockhash\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title SafeCall\\n * @notice Perform low level safe calls\\n */\\nlibrary SafeCall {\\n /**\\n * @notice Perform a low level call without copying any returndata\\n *\\n * @param _target Address to call\\n * @param _gas Amount of gas to pass to the call\\n * @param _value Amount of value to pass to the call\\n * @param _calldata Calldata to pass to the call\\n */\\n function call(\\n address _target,\\n uint256 _gas,\\n uint256 _value,\\n bytes memory _calldata\\n ) internal returns (bool) {\\n bool _success;\\n assembly {\\n _success := call(\\n _gas, // gas\\n _target, // recipient\\n _value, // ether value\\n add(_calldata, 0x20), // inloc\\n mload(_calldata), // inlen\\n 0, // outloc\\n 0 // outlen\\n )\\n }\\n return _success;\\n }\\n}\\n\",\"keccak256\":\"0xbb0621c028c18e9d5a54cf1a8136cf2e77f161de48aeb8d911e230f6b280c9ed\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Types\\n * @notice Contains various types used throughout the Optimism contract system.\\n */\\nlibrary Types {\\n /**\\n * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\\n * timestamp that the output root is posted. This timestamp is used to verify that the\\n * finalization period has passed since the output root was submitted.\\n */\\n struct OutputProposal {\\n bytes32 outputRoot;\\n uint256 timestamp;\\n }\\n\\n /**\\n * @notice Struct representing the elements that are hashed together to generate an output root\\n * which itself represents a snapshot of the L2 state.\\n */\\n struct OutputRootProof {\\n bytes32 version;\\n bytes32 stateRoot;\\n bytes32 messagePasserStorageRoot;\\n bytes32 latestBlockhash;\\n }\\n\\n /**\\n * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\\n * user (as opposed to a system deposit transaction generated by the system).\\n */\\n struct UserDepositTransaction {\\n address from;\\n address to;\\n bool isCreation;\\n uint256 value;\\n uint256 mint;\\n uint64 gasLimit;\\n bytes data;\\n bytes32 l1BlockHash;\\n uint256 logIndex;\\n }\\n\\n /**\\n * @notice Struct representing a withdrawal transaction.\\n */\\n struct WithdrawalTransaction {\\n uint256 nonce;\\n address sender;\\n address target;\\n uint256 value;\\n uint256 gasLimit;\\n bytes data;\\n }\\n}\\n\",\"keccak256\":\"0x69ca98e57a7cbe60cffeb0f76f6f9279010941b1931581e9a35478f30e2546d1\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\\n * @title RLPWriter\\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\\n * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\\n * modifications to improve legibility.\\n */\\nlibrary RLPWriter {\\n /**\\n * @notice RLP encodes a byte string.\\n *\\n * @param _in The byte string to encode.\\n *\\n * @return The RLP encoded string in bytes.\\n */\\n function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\\n bytes memory encoded;\\n\\n if (_in.length == 1 && uint8(_in[0]) < 128) {\\n encoded = _in;\\n } else {\\n encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\\n }\\n\\n return encoded;\\n }\\n\\n /**\\n * @notice RLP encodes a list of RLP encoded byte byte strings.\\n *\\n * @param _in The list of RLP encoded byte strings.\\n *\\n * @return The RLP encoded list of items in bytes.\\n */\\n function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\\n bytes memory list = _flatten(_in);\\n return abi.encodePacked(_writeLength(list.length, 192), list);\\n }\\n\\n /**\\n * @notice RLP encodes a string.\\n *\\n * @param _in The string to encode.\\n *\\n * @return The RLP encoded string in bytes.\\n */\\n function writeString(string memory _in) internal pure returns (bytes memory) {\\n return writeBytes(bytes(_in));\\n }\\n\\n /**\\n * @notice RLP encodes an address.\\n *\\n * @param _in The address to encode.\\n *\\n * @return The RLP encoded address in bytes.\\n */\\n function writeAddress(address _in) internal pure returns (bytes memory) {\\n return writeBytes(abi.encodePacked(_in));\\n }\\n\\n /**\\n * @notice RLP encodes a uint.\\n *\\n * @param _in The uint256 to encode.\\n *\\n * @return The RLP encoded uint256 in bytes.\\n */\\n function writeUint(uint256 _in) internal pure returns (bytes memory) {\\n return writeBytes(_toBinary(_in));\\n }\\n\\n /**\\n * @notice RLP encodes a bool.\\n *\\n * @param _in The bool to encode.\\n *\\n * @return The RLP encoded bool in bytes.\\n */\\n function writeBool(bool _in) internal pure returns (bytes memory) {\\n bytes memory encoded = new bytes(1);\\n encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\\n return encoded;\\n }\\n\\n /**\\n * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\\n *\\n * @param _len The length of the string or the payload.\\n * @param _offset 128 if item is string, 192 if item is list.\\n *\\n * @return RLP encoded bytes.\\n */\\n function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\\n bytes memory encoded;\\n\\n if (_len < 56) {\\n encoded = new bytes(1);\\n encoded[0] = bytes1(uint8(_len) + uint8(_offset));\\n } else {\\n uint256 lenLen;\\n uint256 i = 1;\\n while (_len / i != 0) {\\n lenLen++;\\n i *= 256;\\n }\\n\\n encoded = new bytes(lenLen + 1);\\n encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\\n for (i = 1; i <= lenLen; i++) {\\n encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\\n }\\n }\\n\\n return encoded;\\n }\\n\\n /**\\n * @notice Encode integer in big endian binary form with no leading zeroes.\\n *\\n * @param _x The integer to encode.\\n *\\n * @return RLP encoded bytes.\\n */\\n function _toBinary(uint256 _x) private pure returns (bytes memory) {\\n bytes memory b = abi.encodePacked(_x);\\n\\n uint256 i = 0;\\n for (; i < 32; i++) {\\n if (b[i] != 0) {\\n break;\\n }\\n }\\n\\n bytes memory res = new bytes(32 - i);\\n for (uint256 j = 0; j < res.length; j++) {\\n res[j] = b[i++];\\n }\\n\\n return res;\\n }\\n\\n /**\\n * @custom:attribution https://github.com/Arachnid/solidity-stringutils\\n * @notice Copies a piece of memory to another location.\\n *\\n * @param _dest Destination location.\\n * @param _src Source location.\\n * @param _len Length of memory to copy.\\n */\\n function _memcpy(\\n uint256 _dest,\\n uint256 _src,\\n uint256 _len\\n ) private pure {\\n uint256 dest = _dest;\\n uint256 src = _src;\\n uint256 len = _len;\\n\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n uint256 mask;\\n unchecked {\\n mask = 256**(32 - len) - 1;\\n }\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n\\n /**\\n * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\\n * @notice Flattens a list of byte strings into one byte string.\\n *\\n * @param _list List of byte strings to flatten.\\n *\\n * @return The flattened byte string.\\n */\\n function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\\n if (_list.length == 0) {\\n return new bytes(0);\\n }\\n\\n uint256 len;\\n uint256 i = 0;\\n for (; i < _list.length; i++) {\\n len += _list[i].length;\\n }\\n\\n bytes memory flattened = new bytes(len);\\n uint256 flattenedPtr;\\n assembly {\\n flattenedPtr := add(flattened, 0x20)\\n }\\n\\n for (i = 0; i < _list.length; i++) {\\n bytes memory item = _list[i];\\n\\n uint256 listPtr;\\n assembly {\\n listPtr := add(item, 0x20)\\n }\\n\\n _memcpy(flattenedPtr, listPtr, item.length);\\n flattenedPtr += _list[i].length;\\n }\\n\\n return flattened;\\n }\\n}\\n\",\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {\\n PausableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {\\n ReentrancyGuardUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeCall } from \\\"../libraries/SafeCall.sol\\\";\\nimport { Hashing } from \\\"../libraries/Hashing.sol\\\";\\nimport { Encoding } from \\\"../libraries/Encoding.sol\\\";\\n\\n/**\\n * @custom:legacy\\n * @title CrossDomainMessengerLegacySpacer\\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\\n * libAddressManager variable used to exist. Must be the first contract in the inheritance\\n * tree of the CrossDomainMessenger\\n */\\ncontract CrossDomainMessengerLegacySpacer {\\n /**\\n * @custom:legacy\\n * @custom:spacer libAddressManager\\n * @notice Spacer for backwards compatibility.\\n */\\n address private spacer_0_0_20;\\n}\\n\\n/**\\n * @custom:upgradeable\\n * @title CrossDomainMessenger\\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\\n * cross-chain messenger contracts. It's designed to be a universal interface that only\\n * needs to be extended slightly to provide low-level message passing functionality on each\\n * chain it's deployed on. Currently only designed for message passing between two paired\\n * chains and does not support one-to-many interactions.\\n */\\nabstract contract CrossDomainMessenger is\\n CrossDomainMessengerLegacySpacer,\\n OwnableUpgradeable,\\n PausableUpgradeable,\\n ReentrancyGuardUpgradeable\\n{\\n /**\\n * @notice Current message version identifier.\\n */\\n uint16 public constant MESSAGE_VERSION = 1;\\n\\n /**\\n * @notice Constant overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\\n\\n /**\\n * @notice Numerator for dynamic overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\\n\\n /**\\n * @notice Denominator for dynamic overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\\n\\n /**\\n * @notice Extra gas added to base gas for each byte of calldata in a message.\\n */\\n uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\\n\\n /**\\n * @notice Minimum amount of gas required to relay a message.\\n */\\n uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\\n\\n /**\\n * @notice Amount of gas held in reserve to guarantee that relay execution completes.\\n */\\n uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\\n\\n /**\\n * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\\n * because performing an SSTORE on a non-zero value is significantly cheaper than on a\\n * zero value.\\n */\\n address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\\n\\n /**\\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\\n */\\n address public immutable otherMessenger;\\n\\n /**\\n * @custom:legacy\\n * @custom:spacer blockedMessages\\n * @notice Spacer for backwards compatibility.\\n */\\n mapping(bytes32 => bool) private spacer_201_0_32;\\n\\n /**\\n * @custom:legacy\\n * @custom:spacer relayedMessages\\n * @notice Spacer for backwards compatibility.\\n */\\n mapping(bytes32 => bool) private spacer_202_0_32;\\n\\n /**\\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\\n * be present in this mapping if it has successfully been relayed on this chain, and\\n * can therefore not be relayed again.\\n */\\n mapping(bytes32 => bool) public successfulMessages;\\n\\n /**\\n * @notice Address of the sender of the currently executing message on the other chain. If the\\n * value of this variable is the default value (0x00000000...dead) then no message is\\n * currently being executed. Use the xDomainMessageSender getter which will throw an\\n * error if this is the case.\\n */\\n address internal xDomainMsgSender;\\n\\n /**\\n * @notice Nonce for the next message to be sent, without the message version applied. Use the\\n * messageNonce getter which will insert the message version into the nonce to give you\\n * the actual nonce to be used for the message.\\n */\\n uint240 internal msgNonce;\\n\\n /**\\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\\n * be present in this mapping if it failed to be relayed on this chain at least once.\\n * If a message is successfully relayed on the first attempt, then it will only be\\n * present within the successfulMessages mapping.\\n */\\n mapping(bytes32 => bool) public receivedMessages;\\n\\n /**\\n * @notice Reserve extra slots in the storage layout for future upgrades.\\n * A gap size of 41 was chosen here, so that the first slot used in a child contract\\n * would be a multiple of 50.\\n */\\n uint256[42] private __gap;\\n\\n /**\\n * @notice Emitted whenever a message is sent to the other chain.\\n *\\n * @param target Address of the recipient of the message.\\n * @param sender Address of the sender of the message.\\n * @param message Message to trigger the recipient address with.\\n * @param messageNonce Unique nonce attached to the message.\\n * @param gasLimit Minimum gas limit that the message can be executed with.\\n */\\n event SentMessage(\\n address indexed target,\\n address sender,\\n bytes message,\\n uint256 messageNonce,\\n uint256 gasLimit\\n );\\n\\n /**\\n * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\\n * SentMessage event without breaking the ABI of this contract, this is good enough.\\n *\\n * @param sender Address of the sender of the message.\\n * @param value ETH value sent along with the message to the recipient.\\n */\\n event SentMessageExtension1(address indexed sender, uint256 value);\\n\\n /**\\n * @notice Emitted whenever a message is successfully relayed on this chain.\\n *\\n * @param msgHash Hash of the message that was relayed.\\n */\\n event RelayedMessage(bytes32 indexed msgHash);\\n\\n /**\\n * @notice Emitted whenever a message fails to be relayed on this chain.\\n *\\n * @param msgHash Hash of the message that failed to be relayed.\\n */\\n event FailedRelayedMessage(bytes32 indexed msgHash);\\n\\n /**\\n * @param _otherMessenger Address of the messenger on the paired chain.\\n */\\n constructor(address _otherMessenger) {\\n otherMessenger = _otherMessenger;\\n }\\n\\n /**\\n * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\\n * security mechanism just in case. Owner should be the same as the upgrade wallet to\\n * maintain the security model of the system as a whole.\\n */\\n function pause() external onlyOwner {\\n _pause();\\n }\\n\\n /**\\n * @notice Allows the owner of this contract to resume message relaying once paused.\\n */\\n function unpause() external onlyOwner {\\n _unpause();\\n }\\n\\n /**\\n * @notice Sends a message to some target address on the other chain. Note that if the call\\n * always reverts, then the message will be unrelayable, and any ETH sent will be\\n * permanently locked. The same will occur if the target on the other chain is\\n * considered unsafe (see the _isUnsafeTarget() function).\\n *\\n * @param _target Target contract or wallet address.\\n * @param _message Message to trigger the target address with.\\n * @param _minGasLimit Minimum gas limit that the message can be executed with.\\n */\\n function sendMessage(\\n address _target,\\n bytes calldata _message,\\n uint32 _minGasLimit\\n ) external payable {\\n // Triggers a message to the other messenger. Note that the amount of gas provided to the\\n // message is the amount of gas requested by the user PLUS the base gas value. We want to\\n // guarantee the property that the call to the target contract will always have at least\\n // the minimum gas limit specified by the user.\\n _sendMessage(\\n otherMessenger,\\n baseGas(_message, _minGasLimit),\\n msg.value,\\n abi.encodeWithSelector(\\n this.relayMessage.selector,\\n messageNonce(),\\n msg.sender,\\n _target,\\n msg.value,\\n _minGasLimit,\\n _message\\n )\\n );\\n\\n emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\\n emit SentMessageExtension1(msg.sender, msg.value);\\n\\n unchecked {\\n ++msgNonce;\\n }\\n }\\n\\n /**\\n * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\\n * be executed via cross-chain call from the other messenger OR if the message was\\n * already received once and is currently being replayed.\\n *\\n * @param _nonce Nonce of the message being relayed.\\n * @param _sender Address of the user who sent the message.\\n * @param _target Address that the message is targeted at.\\n * @param _value ETH value to send with the message.\\n * @param _minGasLimit Minimum amount of gas that the message can be executed with.\\n * @param _message Message to send to the target.\\n */\\n function relayMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _minGasLimit,\\n bytes calldata _message\\n ) external payable nonReentrant whenNotPaused {\\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\\n\\n // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\\n // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\\n // to the value or minGasLimit fields, which can create unexpected issues for end-users.\\n require(\\n version == 1,\\n \\\"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\\\"\\n );\\n\\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _minGasLimit,\\n _message\\n );\\n\\n if (_isOtherMessenger()) {\\n // This property should always hold when the message is first submitted (as opposed to\\n // being replayed).\\n assert(msg.value == _value);\\n } else {\\n require(\\n msg.value == 0,\\n \\\"CrossDomainMessenger: value must be zero unless message is from a system address\\\"\\n );\\n\\n require(\\n receivedMessages[versionedHash],\\n \\\"CrossDomainMessenger: message cannot be replayed\\\"\\n );\\n }\\n\\n require(\\n _isUnsafeTarget(_target) == false,\\n \\\"CrossDomainMessenger: cannot send message to blocked system address\\\"\\n );\\n\\n require(\\n successfulMessages[versionedHash] == false,\\n \\\"CrossDomainMessenger: message has already been relayed\\\"\\n );\\n\\n require(\\n gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\\n \\\"CrossDomainMessenger: insufficient gas to relay message\\\"\\n );\\n\\n xDomainMsgSender = _sender;\\n bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\\n\\n if (success == true) {\\n successfulMessages[versionedHash] = true;\\n emit RelayedMessage(versionedHash);\\n } else {\\n receivedMessages[versionedHash] = true;\\n emit FailedRelayedMessage(versionedHash);\\n }\\n }\\n\\n /**\\n * @notice Retrieves the address of the contract or wallet that initiated the currently\\n * executing message on the other chain. Will throw an error if there is no message\\n * currently being executed. Allows the recipient of a call to see who triggered it.\\n *\\n * @return Address of the sender of the currently executing message on the other chain.\\n */\\n function xDomainMessageSender() external view returns (address) {\\n require(\\n xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\\n \\\"CrossDomainMessenger: xDomainMessageSender is not set\\\"\\n );\\n\\n return xDomainMsgSender;\\n }\\n\\n /**\\n * @notice Retrieves the next message nonce. Message version will be added to the upper two\\n * bytes of the message nonce. Message version allows us to treat messages as having\\n * different structures.\\n *\\n * @return Nonce of the next message to be sent, with added message version.\\n */\\n function messageNonce() public view returns (uint256) {\\n return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\\n }\\n\\n /**\\n * @notice Computes the amount of gas required to guarantee that a given message will be\\n * received on the other chain without running out of gas. Guaranteeing that a message\\n * will not run out of gas is important because this ensures that a message can always\\n * be replayed on the other chain if it fails to execute completely.\\n *\\n * @param _message Message to compute the amount of required gas for.\\n * @param _minGasLimit Minimum desired gas limit when message goes to target.\\n *\\n * @return Amount of gas required to guarantee message receipt.\\n */\\n function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\\n return\\n // Dynamic overhead\\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\\n // Calldata overhead\\n (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\\n // Constant overhead\\n MIN_GAS_CONSTANT_OVERHEAD;\\n }\\n\\n /**\\n * @notice Intializer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function __CrossDomainMessenger_init() internal onlyInitializing {\\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\\n __Context_init_unchained();\\n __Ownable_init_unchained();\\n __Pausable_init_unchained();\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n /**\\n * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\\n * contracts because the logic for this depends on the network where the messenger is\\n * being deployed.\\n *\\n * @param _to Recipient of the message on the other chain.\\n * @param _gasLimit Minimum gas limit the message can be executed with.\\n * @param _value Amount of ETH to send with the message.\\n * @param _data Message data.\\n */\\n function _sendMessage(\\n address _to,\\n uint64 _gasLimit,\\n uint256 _value,\\n bytes memory _data\\n ) internal virtual;\\n\\n /**\\n * @notice Checks whether the message is coming from the other messenger. Implemented by child\\n * contracts because the logic for this depends on the network where the messenger is\\n * being deployed.\\n *\\n * @return Whether the message is coming from the other messenger.\\n */\\n function _isOtherMessenger() internal view virtual returns (bool);\\n\\n /**\\n * @notice Checks whether a given call target is a system address that could cause the\\n * messenger to peform an unsafe action. This is NOT a mechanism for blocking user\\n * addresses. This is ONLY used to prevent the execution of messages to specific\\n * system addresses that could cause security issues, e.g., having the\\n * CrossDomainMessenger send messages to itself.\\n *\\n * @param _target Address of the contract to check.\\n *\\n * @return Whether or not the address is an unsafe system address.\\n */\\n function _isUnsafeTarget(address _target) internal view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xead7d44e99f3749f1f45e3f70496c27c2d56e532835c13d02b43ee0d8ff1d593\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.15;\\n\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\n\\n/**\\n * @title Semver\\n * @notice Semver is a simple contract for managing contract versions.\\n */\\ncontract Semver {\\n /**\\n * @notice Contract version number (major).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable PATCH_VERSION;\\n\\n /**\\n * @param _major Version number (major).\\n * @param _minor Version number (minor).\\n * @param _patch Version number (patch).\\n */\\n constructor(\\n uint256 _major,\\n uint256 _minor,\\n uint256 _patch\\n ) {\\n MAJOR_VERSION = _major;\\n MINOR_VERSION = _minor;\\n PATCH_VERSION = _patch;\\n }\\n\\n /**\\n * @notice Returns the full semver contract version.\\n *\\n * @return Semver contract version as a string.\\n */\\n function version() public view returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n Strings.toString(MAJOR_VERSION),\\n \\\".\\\",\\n Strings.toString(MINOR_VERSION),\\n \\\".\\\",\\n Strings.toString(PATCH_VERSION)\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x8215e8fbaace5e06fdf0be26cd8ec224847cf03e89bd78dc8ba3ec2cb429d4fe\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\\n * initialization step. This is essential to configure modules that are added through upgrades and that require\\n * initialization.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized < type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x8cc03c5ac17e8a7396e487cda41fc1f1dfdb91db7d528e6da84bee3b6dd7e167\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/L1/L1ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { ERC721Bridge } from \\\"../universal/op-erc721/ERC721Bridge.sol\\\";\\nimport { IERC721 } from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport { L2ERC721Bridge } from \\\"../L2/L2ERC721Bridge.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title L1ERC721Bridge\\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\\n * acts as an escrow for ERC721 tokens deposited into L2.\\n */\\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\\n /**\\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\\n * by ID was deposited for a given L2 token.\\n */\\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(1, 0, 0)\\n ERC721Bridge(_messenger, _otherBridge)\\n {}\\n\\n /*************************\\n * Cross-chain Functions *\\n *************************/\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyOtherBridge {\\n require(_localToken != address(this), \\\"L1ERC721Bridge: local token cannot be self\\\");\\n\\n // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\\n require(\\n deposits[_localToken][_remoteToken][_tokenId] == true,\\n \\\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\\\"\\n );\\n\\n // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\\n // Bridge.\\n deposits[_localToken][_remoteToken][_tokenId] = false;\\n\\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\\n // withdrawer.\\n IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @inheritdoc ERC721Bridge\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal override {\\n require(_remoteToken != address(0), \\\"ERC721Bridge: remote token cannot be address(0)\\\");\\n\\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\\n bytes memory message = abi.encodeWithSelector(\\n L2ERC721Bridge.finalizeBridgeERC721.selector,\\n _remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Lock token into bridge\\n deposits[_localToken][_remoteToken][_tokenId] = true;\\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\\n\\n // Send calldata into L2\\n messenger.sendMessage(otherBridge, message, _minGasLimit);\\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0x966ae750603761f5636063e4d1441759bd7e140ba933303d31c62220e75c8869\",\"license\":\"MIT\"},\"contracts/L2/L2ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { ERC721Bridge } from \\\"../universal/op-erc721/ERC721Bridge.sol\\\";\\nimport { ERC165Checker } from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\nimport { L1ERC721Bridge } from \\\"../L1/L1ERC721Bridge.sol\\\";\\nimport { IOptimismMintableERC721 } from \\\"../universal/op-erc721/IOptimismMintableERC721.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title L2ERC721Bridge\\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\\n * This contract also acts as a burner for tokens being withdrawn.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n */\\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(1, 0, 0)\\n ERC721Bridge(_messenger, _otherBridge)\\n {}\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyOtherBridge {\\n require(_localToken != address(this), \\\"L2ERC721Bridge: local token cannot be self\\\");\\n\\n // Note that supportsInterface makes a callback to the _localToken address which is user\\n // provided.\\n require(\\n ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\\n \\\"L2ERC721Bridge: local token interface is not compliant\\\"\\n );\\n\\n require(\\n _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\\n \\\"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\\\"\\n );\\n\\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\\n // on L2. Note that safeMint makes a callback to the _to address which is user provided.\\n IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @inheritdoc ERC721Bridge\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal override {\\n require(_remoteToken != address(0), \\\"ERC721Bridge: remote token cannot be address(0)\\\");\\n\\n // Check that the withdrawal is being initiated by the NFT owner\\n require(\\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\\n \\\"Withdrawal is not being initiated by NFT owner\\\"\\n );\\n\\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\\n // slither-disable-next-line reentrancy-events\\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\\n require(\\n remoteToken == _remoteToken,\\n \\\"L2ERC721Bridge: remote token does not match given value\\\"\\n );\\n\\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\\n // usage\\n // slither-disable-next-line reentrancy-events\\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\\n\\n bytes memory message = abi.encodeWithSelector(\\n L1ERC721Bridge.finalizeBridgeERC721.selector,\\n remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Send message to L1 bridge\\n // slither-disable-next-line reentrancy-events\\n messenger.sendMessage(otherBridge, message, _minGasLimit);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0xedcf2403f87c8c72790c053b44ccd762e99f5cdf0f362123288d6893b4c856b5\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport {\\n CrossDomainMessenger\\n} from \\\"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\n/**\\n * @title ERC721Bridge\\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\\n */\\nabstract contract ERC721Bridge {\\n /**\\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeInitiated(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFinalized(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Messenger contract on this domain.\\n */\\n CrossDomainMessenger public immutable messenger;\\n\\n /**\\n * @notice Address of the bridge on the other network.\\n */\\n address public immutable otherBridge;\\n\\n /**\\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\\n */\\n uint256[49] private __gap;\\n\\n /**\\n * @notice Ensures that the caller is a cross-chain message from the other bridge.\\n */\\n modifier onlyOtherBridge() {\\n require(\\n msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\\n \\\"ERC721Bridge: function can only be called from the other bridge\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge) {\\n require(_messenger != address(0), \\\"ERC721Bridge: messenger cannot be address(0)\\\");\\n require(_otherBridge != address(0), \\\"ERC721Bridge: other bridge cannot be address(0)\\\");\\n\\n messenger = CrossDomainMessenger(_messenger);\\n otherBridge = _otherBridge;\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\\n * this function can only be called by EOAs. Smart contract wallets should use the\\n * `bridgeERC721To` function after ensuring that the recipient address on the remote\\n * chain exists. Also note that the current owner of the token on this chain must\\n * approve this contract to operate the NFT before it can be bridged.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\\n * be used to execute any code on the other chain and is only emitted as\\n * extra data for the convenience of off-chain tooling.\\n */\\n function bridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n // Modifier requiring sender to be EOA. This prevents against a user error that would occur\\n // if the sender is a smart contract wallet that has a different address on the remote chain\\n // (or doesn't have an address on the remote chain at all). The user would fail to receive\\n // the NFT if they use this function because it sends the NFT to the same address as the\\n // caller. This check could be bypassed by a malicious contract via initcode, but it takes\\n // care of the user error we want to avoid.\\n require(!Address.isContract(msg.sender), \\\"ERC721Bridge: account is not externally owned\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n msg.sender,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\\n * that the current owner of the token on this chain must approve this contract to\\n * operate the NFT before it can be bridged.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\\n * be used to execute any code on the other chain and is only emitted as\\n * extra data for the convenience of off-chain tooling.\\n */\\n function bridgeERC721To(\\n address _localToken,\\n address _remoteToken,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n require(_to != address(0), \\\"ERC721Bridge: nft recipient cannot be address(0)\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n _to,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Internal function for initiating a token bridge to the other domain.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _from Address of the sender on this domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other domain. Data supplied here will\\n * not be used to execute any code on the other domain and is only emitted\\n * as extra data for the convenience of off-chain tooling.\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal virtual;\\n}\\n\",\"keccak256\":\"0x24898e2e75865a4e35cde2d62518cb4c15a30b7cdae8a1a37624a82ae2a26eb7\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/IOptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {\\n IERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\\\";\\n\\n/**\\n * @title IOptimismMintableERC721\\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\\n */\\ninterface IOptimismMintableERC721 is IERC721Enumerable {\\n /**\\n * @notice Emitted when a token is minted.\\n *\\n * @param account Address of the account the token was minted to.\\n * @param tokenId Token ID of the minted token.\\n */\\n event Mint(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Emitted when a token is burned.\\n *\\n * @param account Address of the account the token was burned from.\\n * @param tokenId Token ID of the burned token.\\n */\\n event Burn(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Chain ID of the chain where the remote token is deployed.\\n */\\n function remoteChainId() external view returns (uint256);\\n\\n /**\\n * @notice Address of the token on the remote domain.\\n */\\n function remoteToken() external view returns (address);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n function bridge() external view returns (address);\\n\\n /**\\n * @notice Mints some token ID for a user, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * @param _to Address of the user to mint the token for.\\n * @param _tokenId Token ID to mint.\\n */\\n function safeMint(address _to, uint256 _tokenId) external;\\n\\n /**\\n * @notice Burns a token ID from a user.\\n *\\n * @param _from Address of the user to burn the token from.\\n * @param _tokenId Token ID to burn.\\n */\\n function burn(address _from, uint256 _tokenId) external;\\n}\\n\",\"keccak256\":\"0xc3703030d0093d65839b02296e3152681fa1c8d717e66ab3f5a7c32ba3fd0a54\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6101206040523480156200001257600080fd5b50604051620014fc380380620014fc833981016040819052620000359162000162565b600160008084846001600160a01b038216620000ad5760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b0381166200011d5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401620000a4565b6001600160a01b039182166080521660a05260c09290925260e05261010052506200019a9050565b80516001600160a01b03811681146200015d57600080fd5b919050565b600080604083850312156200017657600080fd5b620001818362000145565b9150620001916020840162000145565b90509250929050565b60805160a05160c05160e051610100516112fb6200020160003960006102930152600061026a0152600061024101526000818161016c0152818161031f0152610aa6015260008181609c015281816102f5015281816103560152610a7701526112fb6000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80635d93a3fc1161005b5780635d93a3fc146100fd578063761f449314610141578063aa55745214610154578063c89701a21461016757600080fd5b80633687011a146100825780633cb747bf1461009757806354fd4d50146100e8575b600080fd5b610095610090366004610d55565b61018e565b005b6100be7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f061023a565b6040516100df9190610e52565b61013161010b366004610e6c565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b60405190151581526020016100df565b61009561014f366004610ead565b6102dd565b610095610162366004610f45565b61075e565b6100be7f000000000000000000000000000000000000000000000000000000000000000081565b333b15610222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610232868633338888888861081a565b505050505050565b60606102657f0000000000000000000000000000000000000000000000000000000000000000610b91565b61028e7f0000000000000000000000000000000000000000000000000000000000000000610b91565b6102b77f0000000000000000000000000000000000000000000000000000000000000000610b91565b6040516020016102c993929190610fbc565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103fb57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190611032565b73ffffffffffffffffffffffffffffffffffffffff16145b610487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f7468657220627269646765006064820152608401610219565b3073ffffffffffffffffffffffffffffffffffffffff88160361052c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c66000000000000000000000000000000000000000000006064820152608401610219565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146105fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c3120427269646765000000000000006064820152608401610219565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106bb57600080fd5b505af11580156106cf573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8787878760405161074d9493929190611098565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610801576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f742062652061646472657373283029000000000000000000000000000000006064820152608401610219565b610811878733888888888861081a565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff87166108bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4552433732314272696467653a2072656d6f746520746f6b656e2063616e6e6f60448201527f74206265206164647265737328302900000000000000000000000000000000006064820152608401610219565b600063761f449360e01b888a89898988886040516024016108e497969594939291906110d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610a2457600080fd5b505af1158015610a38573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610ad2907f00000000000000000000000000000000000000000000000000000000000000009085908990600401611135565b600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610b7e9493929190611098565b60405180910390a4505050505050505050565b606081600003610bd457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610bfe5780610be8816111a9565b9150610bf79050600a83611210565b9150610bd8565b60008167ffffffffffffffff811115610c1957610c19611224565b6040519080825280601f01601f191660200182016040528015610c43576020820181803683370190505b5090505b8415610cc657610c58600183611253565b9150610c65600a8661126a565b610c7090603061127e565b60f81b818381518110610c8557610c85611296565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610cbf600a86611210565b9450610c47565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cf057600080fd5b50565b803563ffffffff81168114610d0757600080fd5b919050565b60008083601f840112610d1e57600080fd5b50813567ffffffffffffffff811115610d3657600080fd5b602083019150836020828501011115610d4e57600080fd5b9250929050565b60008060008060008060a08789031215610d6e57600080fd5b8635610d7981610cce565b95506020870135610d8981610cce565b945060408701359350610d9e60608801610cf3565b9250608087013567ffffffffffffffff811115610dba57600080fd5b610dc689828a01610d0c565b979a9699509497509295939492505050565b60005b83811015610df3578181015183820152602001610ddb565b83811115610e02576000848401525b50505050565b60008151808452610e20816020860160208601610dd8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610e656020830184610e08565b9392505050565b600080600060608486031215610e8157600080fd5b8335610e8c81610cce565b92506020840135610e9c81610cce565b929592945050506040919091013590565b600080600080600080600060c0888a031215610ec857600080fd5b8735610ed381610cce565b96506020880135610ee381610cce565b95506040880135610ef381610cce565b94506060880135610f0381610cce565b93506080880135925060a088013567ffffffffffffffff811115610f2657600080fd5b610f328a828b01610d0c565b989b979a50959850939692959293505050565b600080600080600080600060c0888a031215610f6057600080fd5b8735610f6b81610cce565b96506020880135610f7b81610cce565b95506040880135610f8b81610cce565b945060608801359350610fa060808901610cf3565b925060a088013567ffffffffffffffff811115610f2657600080fd5b60008451610fce818460208901610dd8565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161100a816001850160208a01610dd8565b60019201918201528351611025816002840160208801610dd8565b0160020195945050505050565b60006020828403121561104457600080fd5b8151610e6581610cce565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006110ce60608301848661104f565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261112860c08301848661104f565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111646060830185610e08565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036111da576111da61117a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261121f5761121f6111e1565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156112655761126561117a565b500390565b600082611279576112796111e1565b500690565b600082198211156112915761129161117a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea2646970667358221220e0cdb7d90e665791c254a8f9e836e4238ad139ec9b459c5b8d78a03279211a1664736f6c634300080f0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80635d93a3fc1161005b5780635d93a3fc146100fd578063761f449314610141578063aa55745214610154578063c89701a21461016757600080fd5b80633687011a146100825780633cb747bf1461009757806354fd4d50146100e8575b600080fd5b610095610090366004610d55565b61018e565b005b6100be7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f061023a565b6040516100df9190610e52565b61013161010b366004610e6c565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b60405190151581526020016100df565b61009561014f366004610ead565b6102dd565b610095610162366004610f45565b61075e565b6100be7f000000000000000000000000000000000000000000000000000000000000000081565b333b15610222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610232868633338888888861081a565b505050505050565b60606102657f0000000000000000000000000000000000000000000000000000000000000000610b91565b61028e7f0000000000000000000000000000000000000000000000000000000000000000610b91565b6102b77f0000000000000000000000000000000000000000000000000000000000000000610b91565b6040516020016102c993929190610fbc565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103fb57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190611032565b73ffffffffffffffffffffffffffffffffffffffff16145b610487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f7468657220627269646765006064820152608401610219565b3073ffffffffffffffffffffffffffffffffffffffff88160361052c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c66000000000000000000000000000000000000000000006064820152608401610219565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146105fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c3120427269646765000000000000006064820152608401610219565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106bb57600080fd5b505af11580156106cf573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8787878760405161074d9493929190611098565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610801576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f742062652061646472657373283029000000000000000000000000000000006064820152608401610219565b610811878733888888888861081a565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff87166108bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4552433732314272696467653a2072656d6f746520746f6b656e2063616e6e6f60448201527f74206265206164647265737328302900000000000000000000000000000000006064820152608401610219565b600063761f449360e01b888a89898988886040516024016108e497969594939291906110d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610a2457600080fd5b505af1158015610a38573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610ad2907f00000000000000000000000000000000000000000000000000000000000000009085908990600401611135565b600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610b7e9493929190611098565b60405180910390a4505050505050505050565b606081600003610bd457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610bfe5780610be8816111a9565b9150610bf79050600a83611210565b9150610bd8565b60008167ffffffffffffffff811115610c1957610c19611224565b6040519080825280601f01601f191660200182016040528015610c43576020820181803683370190505b5090505b8415610cc657610c58600183611253565b9150610c65600a8661126a565b610c7090603061127e565b60f81b818381518110610c8557610c85611296565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610cbf600a86611210565b9450610c47565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cf057600080fd5b50565b803563ffffffff81168114610d0757600080fd5b919050565b60008083601f840112610d1e57600080fd5b50813567ffffffffffffffff811115610d3657600080fd5b602083019150836020828501011115610d4e57600080fd5b9250929050565b60008060008060008060a08789031215610d6e57600080fd5b8635610d7981610cce565b95506020870135610d8981610cce565b945060408701359350610d9e60608801610cf3565b9250608087013567ffffffffffffffff811115610dba57600080fd5b610dc689828a01610d0c565b979a9699509497509295939492505050565b60005b83811015610df3578181015183820152602001610ddb565b83811115610e02576000848401525b50505050565b60008151808452610e20816020860160208601610dd8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610e656020830184610e08565b9392505050565b600080600060608486031215610e8157600080fd5b8335610e8c81610cce565b92506020840135610e9c81610cce565b929592945050506040919091013590565b600080600080600080600060c0888a031215610ec857600080fd5b8735610ed381610cce565b96506020880135610ee381610cce565b95506040880135610ef381610cce565b94506060880135610f0381610cce565b93506080880135925060a088013567ffffffffffffffff811115610f2657600080fd5b610f328a828b01610d0c565b989b979a50959850939692959293505050565b600080600080600080600060c0888a031215610f6057600080fd5b8735610f6b81610cce565b96506020880135610f7b81610cce565b95506040880135610f8b81610cce565b945060608801359350610fa060808901610cf3565b925060a088013567ffffffffffffffff811115610f2657600080fd5b60008451610fce818460208901610dd8565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161100a816001850160208a01610dd8565b60019201918201528351611025816002840160208801610dd8565b0160020195945050505050565b60006020828403121561104457600080fd5b8151610e6581610cce565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006110ce60608301848661104f565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261112860c08301848661104f565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111646060830185610e08565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036111da576111da61117a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261121f5761121f6111e1565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156112655761126561117a565b500390565b600082611279576112796111e1565b500690565b600082198211156112915761129161117a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea2646970667358221220e0cdb7d90e665791c254a8f9e836e4238ad139ec9b459c5b8d78a03279211a1664736f6c634300080f0033", + "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": { + "custom:semver": "1.0.0", + "params": { + "_messenger": "Address of the CrossDomainMessenger on this network.", + "_otherBridge": "Address of the ERC721 bridge on the other 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." + } + }, + "version()": { + "returns": { + "_0": "Semver contract version as a string." + } + } + }, + "title": "L1ERC721Bridge", + "version": 1 + }, + "userdoc": { + "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." + } + }, + "kind": "user", + "methods": { + "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." + }, + "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." + }, + "messenger()": { + "notice": "Messenger contract on this domain." + }, + "otherBridge()": { + "notice": "Address of the bridge on the other network." + }, + "version()": { + "notice": "Returns the full semver contract version." + } + }, + "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.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 8088, + "contract": "contracts/L1/L1ERC721Bridge.sol:L1ERC721Bridge", + "label": "__gap", + "offset": 0, + "slot": "0", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 6775, + "contract": "contracts/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)))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "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" + } + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/ethereum/L1ERC721BridgeProxy.json b/packages/contracts-periphery/deployments/ethereum/L1ERC721BridgeProxy.json new file mode 100644 index 0000000000000..6be5dc01aedd1 --- /dev/null +++ b/packages/contracts-periphery/deployments/ethereum/L1ERC721BridgeProxy.json @@ -0,0 +1,257 @@ +{ + "address": "0x5a7749f83b81B301cAb5f48EB8516B986DAef23D", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x7583d011cf1593fb1ffc79b097b0a365192c87dfdccbf860e1ad3f1425a305ef", + "receipt": { + "to": null, + "from": "0x53A6eecC2dD4795Fcc68940ddc6B4d53Bd88Bd9E", + "contractAddress": "0x5a7749f83b81B301cAb5f48EB8516B986DAef23D", + "transactionIndex": 140, + "gasUsed": "532674", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000800000000000000000000000000", + "blockHash": "0xa5c98ae09c1db0857551a9eaca6d88e1bff5f8103814795c0ed1e7863e16a6d5", + "transactionHash": "0x7583d011cf1593fb1ffc79b097b0a365192c87dfdccbf860e1ad3f1425a305ef", + "logs": [ + { + "transactionIndex": 140, + "blockNumber": 15677422, + "transactionHash": "0x7583d011cf1593fb1ffc79b097b0a365192c87dfdccbf860e1ad3f1425a305ef", + "address": "0x5a7749f83b81B301cAb5f48EB8516B986DAef23D", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000053a6eecc2dd4795fcc68940ddc6b4d53bd88bd9e", + "logIndex": 251, + "blockHash": "0xa5c98ae09c1db0857551a9eaca6d88e1bff5f8103814795c0ed1e7863e16a6d5" + } + ], + "blockNumber": 15677422, + "cumulativeGasUsed": "12586381", + "status": 1, + "byzantium": true + }, + "args": [ + "0x53A6eecC2dD4795Fcc68940ddc6B4d53Bd88Bd9E" + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"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\"}}},\"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.\"}}},\"title\":\"Proxy\",\"version\":1},\"userdoc\":{\"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.\"}},\"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.\"},\"implementation()\":{\"notice\":\"Queries the implementation address.\"},\"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.\"}},\"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.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title Proxy\\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\\n * if the caller is address(0), meaning that the call originated from an off-chain\\n * simulation.\\n */\\ncontract Proxy {\\n /**\\n * @notice The storage slot that holds the address of the implementation.\\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n */\\n bytes32 internal constant IMPLEMENTATION_KEY =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @notice The storage slot that holds the address of the owner.\\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n */\\n bytes32 internal constant OWNER_KEY =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @notice An event that is emitted each time the implementation is changed. This event is part\\n * of the EIP-1967 specification.\\n *\\n * @param implementation The address of the implementation contract\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\\n * EIP-1967 specification.\\n *\\n * @param previousAdmin The previous owner of the contract\\n * @param newAdmin The new owner of the contract\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\\n * eth_call to interact with this proxy without needing to use low-level storage\\n * inspection. We assume that nobody is able to trigger calls from address(0) during\\n * normal EVM execution.\\n */\\n modifier proxyCallIfNotAdmin() {\\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\\n _;\\n } else {\\n // This WILL halt the call frame on completion.\\n _doProxyCall();\\n }\\n }\\n\\n /**\\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\\n * EIP-1967 admin storage slot so that accidental storage collision with the\\n * implementation is not possible.\\n *\\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\\n * transparent proxy interface.\\n */\\n constructor(address _admin) {\\n _changeAdmin(_admin);\\n }\\n\\n // slither-disable-next-line locked-ether\\n receive() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n // slither-disable-next-line locked-ether\\n fallback() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n /**\\n * @notice Set the implementation contract address. The code at the given address will execute\\n * when this contract is called.\\n *\\n * @param _implementation Address of the implementation contract.\\n */\\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\\n _setImplementation(_implementation);\\n }\\n\\n /**\\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\\n * atomic execution of initialization-based upgrades.\\n *\\n * @param _implementation Address of the implementation contract.\\n * @param _data Calldata to delegatecall the new implementation with.\\n */\\n function upgradeToAndCall(address _implementation, bytes calldata _data)\\n external\\n payable\\n proxyCallIfNotAdmin\\n returns (bytes memory)\\n {\\n _setImplementation(_implementation);\\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\\n require(success, \\\"Proxy: delegatecall to new implementation contract failed\\\");\\n return returndata;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\\n _changeAdmin(_admin);\\n }\\n\\n /**\\n * @notice Gets the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function admin() external proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() external proxyCallIfNotAdmin returns (address) {\\n return _getImplementation();\\n }\\n\\n /**\\n * @notice Sets the implementation address.\\n *\\n * @param _implementation New implementation address.\\n */\\n function _setImplementation(address _implementation) internal {\\n assembly {\\n sstore(IMPLEMENTATION_KEY, _implementation)\\n }\\n emit Upgraded(_implementation);\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function _changeAdmin(address _admin) internal {\\n address previous = _getAdmin();\\n assembly {\\n sstore(OWNER_KEY, _admin)\\n }\\n emit AdminChanged(previous, _admin);\\n }\\n\\n /**\\n * @notice Performs the proxy call via a delegatecall.\\n */\\n function _doProxyCall() internal {\\n address impl = _getImplementation();\\n require(impl != address(0), \\\"Proxy: implementation not initialized\\\");\\n\\n assembly {\\n // Copy calldata into memory at 0x0....calldatasize.\\n calldatacopy(0x0, 0x0, calldatasize())\\n\\n // Perform the delegatecall, make sure to pass all available gas.\\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\\n\\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\\n // overwrite the calldata that we just copied into memory but that doesn't really\\n // matter because we'll be returning in a second anyway.\\n returndatacopy(0x0, 0x0, returndatasize())\\n\\n // Success == 0 means a revert. We'll revert too and pass the data up.\\n if iszero(success) {\\n revert(0x0, returndatasize())\\n }\\n\\n // Otherwise we'll just return and pass the data up.\\n return(0x0, returndatasize())\\n }\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n address impl;\\n assembly {\\n impl := sload(IMPLEMENTATION_KEY)\\n }\\n return impl;\\n }\\n\\n /**\\n * @notice Queries the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function _getAdmin() internal view returns (address) {\\n address owner;\\n assembly {\\n owner := sload(OWNER_KEY)\\n }\\n return owner;\\n }\\n}\\n\",\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5060405161094138038061094183398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206109218339815191525490565b600080516020610921833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610830806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033", + "devdoc": { + "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" + } + } + }, + "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." + } + } + }, + "title": "Proxy", + "version": 1 + }, + "userdoc": { + "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." + } + }, + "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." + }, + "implementation()": { + "notice": "Queries the implementation address." + }, + "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." + } + }, + "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.", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/ethereum/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json b/packages/contracts-periphery/deployments/ethereum/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json new file mode 100644 index 0000000000000..91d5f99068af8 --- /dev/null +++ b/packages/contracts-periphery/deployments/ethereum/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json @@ -0,0 +1,173 @@ +{ + "language": "Solidity", + "sources": { + "contracts/L1/L1ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L1ERC721Bridge\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as an escrow for ERC721 tokens deposited into L2.\n */\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\n * by ID was deposited for a given L2 token.\n */\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\n * execute any code on L2 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L1ERC721Bridge: local token cannot be self\");\n\n // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\n require(\n deposits[_localToken][_remoteToken][_tokenId] == true,\n \"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\"\n );\n\n // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\n // Bridge.\n deposits[_localToken][_remoteToken][_tokenId] = false;\n\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\n // withdrawer.\n IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\n bytes memory message = abi.encodeWithSelector(\n L2ERC721Bridge.finalizeBridgeERC721.selector,\n _remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Lock token into bridge\n deposits[_localToken][_remoteToken][_tokenId] = true;\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\n\n // Send calldata into L2\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "contracts/universal/op-erc721/ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n CrossDomainMessenger\n} from \"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title ERC721Bridge\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\n */\nabstract contract ERC721Bridge {\n /**\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable messenger;\n\n /**\n * @notice Address of the bridge on the other network.\n */\n address public immutable otherBridge;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[49] private __gap;\n\n /**\n * @notice Ensures that the caller is a cross-chain message from the other bridge.\n */\n modifier onlyOtherBridge() {\n require(\n msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\n \"ERC721Bridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge) {\n require(_messenger != address(0), \"ERC721Bridge: messenger cannot be address(0)\");\n require(_otherBridge != address(0), \"ERC721Bridge: other bridge cannot be address(0)\");\n\n messenger = CrossDomainMessenger(_messenger);\n otherBridge = _otherBridge;\n }\n\n /**\n * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\n * this function can only be called by EOAs. Smart contract wallets should use the\n * `bridgeERC721To` function after ensuring that the recipient address on the remote\n * chain exists. Also note that the current owner of the token on this chain must\n * approve this contract to operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721(\n address _localToken,\n address _remoteToken,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n // Modifier requiring sender to be EOA. This prevents against a user error that would occur\n // if the sender is a smart contract wallet that has a different address on the remote chain\n // (or doesn't have an address on the remote chain at all). The user would fail to receive\n // the NFT if they use this function because it sends the NFT to the same address as the\n // caller. This check could be bypassed by a malicious contract via initcode, but it takes\n // care of the user error we want to avoid.\n require(!Address.isContract(msg.sender), \"ERC721Bridge: account is not externally owned\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\n * that the current owner of the token on this chain must approve this contract to\n * operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n require(_to != address(0), \"ERC721Bridge: nft recipient cannot be address(0)\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Internal function for initiating a token bridge to the other domain.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _from Address of the sender on this domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other domain. Data supplied here will\n * not be used to execute any code on the other domain and is only emitted\n * as extra data for the convenience of off-chain tooling.\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal virtual;\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "contracts/L2/L2ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/op-erc721/IOptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L2ERC721Bridge\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\n * This contract also acts as a burner for tokens being withdrawn.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n */\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\n * execute any code on L1 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L2ERC721Bridge: local token cannot be self\");\n\n // Note that supportsInterface makes a callback to the _localToken address which is user\n // provided.\n require(\n ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\n \"L2ERC721Bridge: local token interface is not compliant\"\n );\n\n require(\n _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\n \"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\"\n );\n\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\n // on L2. Note that safeMint makes a callback to the _to address which is user provided.\n IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Check that the withdrawal is being initiated by the NFT owner\n require(\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\n \"Withdrawal is not being initiated by NFT owner\"\n );\n\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\n // slither-disable-next-line reentrancy-events\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\n require(\n remoteToken == _remoteToken,\n \"L2ERC721Bridge: remote token does not match given value\"\n );\n\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\n // usage\n // slither-disable-next-line reentrancy-events\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\n\n bytes memory message = abi.encodeWithSelector(\n L1ERC721Bridge.finalizeBridgeERC721.selector,\n remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Send message to L1 bridge\n // slither-disable-next-line reentrancy-events\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\n\n/**\n * @title Semver\n * @notice Semver is a simple contract for managing contract versions.\n */\ncontract Semver {\n /**\n * @notice Contract version number (major).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable PATCH_VERSION;\n\n /**\n * @param _major Version number (major).\n * @param _minor Version number (minor).\n * @param _patch Version number (patch).\n */\n constructor(\n uint256 _major,\n uint256 _minor,\n uint256 _patch\n ) {\n MAJOR_VERSION = _major;\n MINOR_VERSION = _minor;\n PATCH_VERSION = _patch;\n }\n\n /**\n * @notice Returns the full semver contract version.\n *\n * @return Semver contract version as a string.\n */\n function version() public view returns (string memory) {\n return\n string(\n abi.encodePacked(\n Strings.toString(MAJOR_VERSION),\n \".\",\n Strings.toString(MINOR_VERSION),\n \".\",\n Strings.toString(PATCH_VERSION)\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n PausableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {\n ReentrancyGuardUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * libAddressManager variable used to exist. Must be the first contract in the inheritance\n * tree of the CrossDomainMessenger\n */\ncontract CrossDomainMessengerLegacySpacer {\n /**\n * @custom:legacy\n * @custom:spacer libAddressManager\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n}\n\n/**\n * @custom:upgradeable\n * @title CrossDomainMessenger\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\n * cross-chain messenger contracts. It's designed to be a universal interface that only\n * needs to be extended slightly to provide low-level message passing functionality on each\n * chain it's deployed on. Currently only designed for message passing between two paired\n * chains and does not support one-to-many interactions.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer,\n OwnableUpgradeable,\n PausableUpgradeable,\n ReentrancyGuardUpgradeable\n{\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Constant overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\n\n /**\n * @notice Numerator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\n\n /**\n * @notice Denominator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\n\n /**\n * @notice Extra gas added to base gas for each byte of calldata in a message.\n */\n uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Minimum amount of gas required to relay a message.\n */\n uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\n\n /**\n * @notice Amount of gas held in reserve to guarantee that relay execution completes.\n */\n uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\n\n /**\n * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\n * because performing an SSTORE on a non-zero value is significantly cheaper than on a\n * zero value.\n */\n address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable otherMessenger;\n\n /**\n * @custom:legacy\n * @custom:spacer blockedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_201_0_32;\n\n /**\n * @custom:legacy\n * @custom:spacer relayedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_202_0_32;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it has successfully been relayed on this chain, and\n * can therefore not be relayed again.\n */\n mapping(bytes32 => bool) public successfulMessages;\n\n /**\n * @notice Address of the sender of the currently executing message on the other chain. If the\n * value of this variable is the default value (0x00000000...dead) then no message is\n * currently being executed. Use the xDomainMessageSender getter which will throw an\n * error if this is the case.\n */\n address internal xDomainMsgSender;\n\n /**\n * @notice Nonce for the next message to be sent, without the message version applied. Use the\n * messageNonce getter which will insert the message version into the nonce to give you\n * the actual nonce to be used for the message.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it failed to be relayed on this chain at least once.\n * If a message is successfully relayed on the first attempt, then it will only be\n * present within the successfulMessages mapping.\n */\n mapping(bytes32 => bool) public receivedMessages;\n\n /**\n * @notice Reserve extra slots in the storage layout for future upgrades.\n * A gap size of 41 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[42] private __gap;\n\n /**\n * @notice Emitted whenever a message is sent to the other chain.\n *\n * @param target Address of the recipient of the message.\n * @param sender Address of the sender of the message.\n * @param message Message to trigger the recipient address with.\n * @param messageNonce Unique nonce attached to the message.\n * @param gasLimit Minimum gas limit that the message can be executed with.\n */\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n /**\n * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\n * SentMessage event without breaking the ABI of this contract, this is good enough.\n *\n * @param sender Address of the sender of the message.\n * @param value ETH value sent along with the message to the recipient.\n */\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n /**\n * @notice Emitted whenever a message is successfully relayed on this chain.\n *\n * @param msgHash Hash of the message that was relayed.\n */\n event RelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @notice Emitted whenever a message fails to be relayed on this chain.\n *\n * @param msgHash Hash of the message that failed to be relayed.\n */\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @param _otherMessenger Address of the messenger on the paired chain.\n */\n constructor(address _otherMessenger) {\n otherMessenger = _otherMessenger;\n }\n\n /**\n * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\n * security mechanism just in case. Owner should be the same as the upgrade wallet to\n * maintain the security model of the system as a whole.\n */\n function pause() external onlyOwner {\n _pause();\n }\n\n /**\n * @notice Allows the owner of this contract to resume message relaying once paused.\n */\n function unpause() external onlyOwner {\n _unpause();\n }\n\n /**\n * @notice Sends a message to some target address on the other chain. Note that if the call\n * always reverts, then the message will be unrelayable, and any ETH sent will be\n * permanently locked. The same will occur if the target on the other chain is\n * considered unsafe (see the _isUnsafeTarget() function).\n *\n * @param _target Target contract or wallet address.\n * @param _message Message to trigger the target address with.\n * @param _minGasLimit Minimum gas limit that the message can be executed with.\n */\n function sendMessage(\n address _target,\n bytes calldata _message,\n uint32 _minGasLimit\n ) external payable {\n // Triggers a message to the other messenger. Note that the amount of gas provided to the\n // message is the amount of gas requested by the user PLUS the base gas value. We want to\n // guarantee the property that the call to the target contract will always have at least\n // the minimum gas limit specified by the user.\n _sendMessage(\n otherMessenger,\n baseGas(_message, _minGasLimit),\n msg.value,\n abi.encodeWithSelector(\n this.relayMessage.selector,\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _minGasLimit,\n _message\n )\n );\n\n emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\n emit SentMessageExtension1(msg.sender, msg.value);\n\n unchecked {\n ++msgNonce;\n }\n }\n\n /**\n * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\n * be executed via cross-chain call from the other messenger OR if the message was\n * already received once and is currently being replayed.\n *\n * @param _nonce Nonce of the message being relayed.\n * @param _sender Address of the user who sent the message.\n * @param _target Address that the message is targeted at.\n * @param _value ETH value to send with the message.\n * @param _minGasLimit Minimum amount of gas that the message can be executed with.\n * @param _message Message to send to the target.\n */\n function relayMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _minGasLimit,\n bytes calldata _message\n ) external payable nonReentrant whenNotPaused {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n\n // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\n // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\n // to the value or minGasLimit fields, which can create unexpected issues for end-users.\n require(\n version == 1,\n \"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\"\n );\n\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n if (_isOtherMessenger()) {\n // This property should always hold when the message is first submitted (as opposed to\n // being replayed).\n assert(msg.value == _value);\n } else {\n require(\n msg.value == 0,\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n\n require(\n receivedMessages[versionedHash],\n \"CrossDomainMessenger: message cannot be replayed\"\n );\n }\n\n require(\n _isUnsafeTarget(_target) == false,\n \"CrossDomainMessenger: cannot send message to blocked system address\"\n );\n\n require(\n successfulMessages[versionedHash] == false,\n \"CrossDomainMessenger: message has already been relayed\"\n );\n\n require(\n gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\n \"CrossDomainMessenger: insufficient gas to relay message\"\n );\n\n xDomainMsgSender = _sender;\n bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n\n if (success == true) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n receivedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n }\n }\n\n /**\n * @notice Retrieves the address of the contract or wallet that initiated the currently\n * executing message on the other chain. Will throw an error if there is no message\n * currently being executed. Allows the recipient of a call to see who triggered it.\n *\n * @return Address of the sender of the currently executing message on the other chain.\n */\n function xDomainMessageSender() external view returns (address) {\n require(\n xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\n \"CrossDomainMessenger: xDomainMessageSender is not set\"\n );\n\n return xDomainMsgSender;\n }\n\n /**\n * @notice Retrieves the next message nonce. Message version will be added to the upper two\n * bytes of the message nonce. Message version allows us to treat messages as having\n * different structures.\n *\n * @return Nonce of the next message to be sent, with added message version.\n */\n function messageNonce() public view returns (uint256) {\n return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\n }\n\n /**\n * @notice Computes the amount of gas required to guarantee that a given message will be\n * received on the other chain without running out of gas. Guaranteeing that a message\n * will not run out of gas is important because this ensures that a message can always\n * be replayed on the other chain if it fails to execute completely.\n *\n * @param _message Message to compute the amount of required gas for.\n * @param _minGasLimit Minimum desired gas limit when message goes to target.\n *\n * @return Amount of gas required to guarantee message receipt.\n */\n function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\n return\n // Dynamic overhead\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\n // Constant overhead\n MIN_GAS_CONSTANT_OVERHEAD;\n }\n\n /**\n * @notice Intializer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __CrossDomainMessenger_init() internal onlyInitializing {\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n __ReentrancyGuard_init_unchained();\n }\n\n /**\n * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @param _to Recipient of the message on the other chain.\n * @param _gasLimit Minimum gas limit the message can be executed with.\n * @param _value Amount of ETH to send with the message.\n * @param _data Message data.\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal virtual;\n\n /**\n * @notice Checks whether the message is coming from the other messenger. Implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @return Whether the message is coming from the other messenger.\n */\n function _isOtherMessenger() internal view virtual returns (bool);\n\n /**\n * @notice Checks whether a given call target is a system address that could cause the\n * messenger to peform an unsafe action. This is NOT a mechanism for blocking user\n * addresses. This is ONLY used to prevent the execution of messages to specific\n * system addresses that could cause security issues, e.g., having the\n * CrossDomainMessenger send messages to itself.\n *\n * @param _target Address of the contract to check.\n *\n * @return Whether or not the address is an unsafe system address.\n */\n function _isUnsafeTarget(address _target) internal view virtual returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title SafeCall\n * @notice Perform low level safe calls\n */\nlibrary SafeCall {\n /**\n * @notice Perform a low level call without copying any returndata\n *\n * @param _target Address to call\n * @param _gas Amount of gas to pass to the call\n * @param _value Amount of value to pass to the call\n * @param _calldata Calldata to pass to the call\n */\n function call(\n address _target,\n uint256 _gas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n assembly {\n _success := call(\n _gas, // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Encoding } from \"./Encoding.sol\";\n\n/**\n * @title Hashing\n * @notice Hashing handles Optimism's various different hashing schemes.\n */\nlibrary Hashing {\n /**\n * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\n * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\n * system.\n *\n * @param _tx User deposit transaction to hash.\n *\n * @return Hash of the RLP encoded L2 deposit transaction.\n */\n function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return keccak256(Encoding.encodeDepositTransaction(_tx));\n }\n\n /**\n * @notice Computes the deposit transaction's \"source hash\", a value that guarantees the hash\n * of the L2 transaction that corresponds to a deposit is unique and is\n * deterministically generated from L1 transaction data.\n *\n * @param _l1BlockHash Hash of the L1 block where the deposit was included.\n * @param _logIndex The index of the log that created the deposit transaction.\n *\n * @return Hash of the deposit transaction's \"source hash\".\n */\n function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\n internal\n pure\n returns (bytes32)\n {\n bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\n return keccak256(abi.encode(bytes32(0), depositId));\n }\n\n /**\n * @notice Hashes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n if (version == 0) {\n return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Hashing: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes32) {\n return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\n }\n\n /**\n * @notice Hashes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n return\n keccak256(\n Encoding.encodeCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n )\n );\n }\n\n /**\n * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\n *\n * @param _tx Withdrawal transaction to hash.\n *\n * @return Hashed withdrawal transaction.\n */\n function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\n );\n }\n\n /**\n * @notice Hashes the various elements of an output root proof into an output root hash which\n * can be used to check if the proof is valid.\n *\n * @param _outputRootProof Output root proof which should hash to an output root.\n *\n * @return Hashed output root proof.\n */\n function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(\n _outputRootProof.version,\n _outputRootProof.stateRoot,\n _outputRootProof.messagePasserStorageRoot,\n _outputRootProof.latestBlockhash\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Hashing } from \"./Hashing.sol\";\nimport { RLPWriter } from \"./rlp/RLPWriter.sol\";\n\n/**\n * @title Encoding\n * @notice Encoding handles Optimism's various different encoding schemes.\n */\nlibrary Encoding {\n /**\n * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\n * to the L2 system. Useful for searching for a deposit in the L2 system. The\n * transaction is prefixed with 0x7e to identify its EIP-2718 type.\n *\n * @param _tx User deposit transaction to encode.\n *\n * @return RLP encoded L2 deposit transaction.\n */\n function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes memory)\n {\n bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\n bytes[] memory raw = new bytes[](8);\n raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\n raw[1] = RLPWriter.writeAddress(_tx.from);\n raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\"\") : RLPWriter.writeAddress(_tx.to);\n raw[3] = RLPWriter.writeUint(_tx.mint);\n raw[4] = RLPWriter.writeUint(_tx.value);\n raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\n raw[6] = RLPWriter.writeBool(false);\n raw[7] = RLPWriter.writeBytes(_tx.data);\n return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\n }\n\n /**\n * @notice Encodes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n (, uint16 version) = decodeVersionedNonce(_nonce);\n if (version == 0) {\n return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Encoding: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _data,\n _nonce\n );\n }\n\n /**\n * @notice Encodes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(uint256,address,address,uint256,uint256,bytes)\",\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n }\n\n /**\n * @notice Adds a version number into the first two bytes of a message nonce.\n *\n * @param _nonce Message nonce to encode into.\n * @param _version Version number to encode into the message nonce.\n *\n * @return Message nonce with version encoded into the first two bytes.\n */\n function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\n uint256 nonce;\n assembly {\n nonce := or(shl(240, _version), _nonce)\n }\n return nonce;\n }\n\n /**\n * @notice Pulls the version out of a version-encoded nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n *\n * @return Nonce without encoded version.\n * @return Version of the message.\n */\n function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\n uint240 nonce;\n uint16 version;\n assembly {\n nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n version := shr(240, _nonce)\n }\n return (nonce, version);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Types\n * @notice Contains various types used throughout the Optimism contract system.\n */\nlibrary Types {\n /**\n * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\n * timestamp that the output root is posted. This timestamp is used to verify that the\n * finalization period has passed since the output root was submitted.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint256 timestamp;\n }\n\n /**\n * @notice Struct representing the elements that are hashed together to generate an output root\n * which itself represents a snapshot of the L2 state.\n */\n struct OutputRootProof {\n bytes32 version;\n bytes32 stateRoot;\n bytes32 messagePasserStorageRoot;\n bytes32 latestBlockhash;\n }\n\n /**\n * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\n * user (as opposed to a system deposit transaction generated by the system).\n */\n struct UserDepositTransaction {\n address from;\n address to;\n bool isCreation;\n uint256 value;\n uint256 mint;\n uint64 gasLimit;\n bytes data;\n bytes32 l1BlockHash;\n uint256 logIndex;\n }\n\n /**\n * @notice Struct representing a withdrawal transaction.\n */\n struct WithdrawalTransaction {\n uint256 nonce;\n address sender;\n address target;\n uint256 value;\n uint256 gasLimit;\n bytes data;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\n * @title RLPWriter\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\n * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\n * modifications to improve legibility.\n */\nlibrary RLPWriter {\n /**\n * @notice RLP encodes a byte string.\n *\n * @param _in The byte string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_in.length == 1 && uint8(_in[0]) < 128) {\n encoded = _in;\n } else {\n encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\n }\n\n return encoded;\n }\n\n /**\n * @notice RLP encodes a list of RLP encoded byte byte strings.\n *\n * @param _in The list of RLP encoded byte strings.\n *\n * @return The RLP encoded list of items in bytes.\n */\n function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\n bytes memory list = _flatten(_in);\n return abi.encodePacked(_writeLength(list.length, 192), list);\n }\n\n /**\n * @notice RLP encodes a string.\n *\n * @param _in The string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeString(string memory _in) internal pure returns (bytes memory) {\n return writeBytes(bytes(_in));\n }\n\n /**\n * @notice RLP encodes an address.\n *\n * @param _in The address to encode.\n *\n * @return The RLP encoded address in bytes.\n */\n function writeAddress(address _in) internal pure returns (bytes memory) {\n return writeBytes(abi.encodePacked(_in));\n }\n\n /**\n * @notice RLP encodes a uint.\n *\n * @param _in The uint256 to encode.\n *\n * @return The RLP encoded uint256 in bytes.\n */\n function writeUint(uint256 _in) internal pure returns (bytes memory) {\n return writeBytes(_toBinary(_in));\n }\n\n /**\n * @notice RLP encodes a bool.\n *\n * @param _in The bool to encode.\n *\n * @return The RLP encoded bool in bytes.\n */\n function writeBool(bool _in) internal pure returns (bytes memory) {\n bytes memory encoded = new bytes(1);\n encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n return encoded;\n }\n\n /**\n * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\n *\n * @param _len The length of the string or the payload.\n * @param _offset 128 if item is string, 192 if item is list.\n *\n * @return RLP encoded bytes.\n */\n function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_len < 56) {\n encoded = new bytes(1);\n encoded[0] = bytes1(uint8(_len) + uint8(_offset));\n } else {\n uint256 lenLen;\n uint256 i = 1;\n while (_len / i != 0) {\n lenLen++;\n i *= 256;\n }\n\n encoded = new bytes(lenLen + 1);\n encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\n for (i = 1; i <= lenLen; i++) {\n encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\n }\n }\n\n return encoded;\n }\n\n /**\n * @notice Encode integer in big endian binary form with no leading zeroes.\n *\n * @param _x The integer to encode.\n *\n * @return RLP encoded bytes.\n */\n function _toBinary(uint256 _x) private pure returns (bytes memory) {\n bytes memory b = abi.encodePacked(_x);\n\n uint256 i = 0;\n for (; i < 32; i++) {\n if (b[i] != 0) {\n break;\n }\n }\n\n bytes memory res = new bytes(32 - i);\n for (uint256 j = 0; j < res.length; j++) {\n res[j] = b[i++];\n }\n\n return res;\n }\n\n /**\n * @custom:attribution https://github.com/Arachnid/solidity-stringutils\n * @notice Copies a piece of memory to another location.\n *\n * @param _dest Destination location.\n * @param _src Source location.\n * @param _len Length of memory to copy.\n */\n function _memcpy(\n uint256 _dest,\n uint256 _src,\n uint256 _len\n ) private pure {\n uint256 dest = _dest;\n uint256 src = _src;\n uint256 len = _len;\n\n for (; len >= 32; len -= 32) {\n assembly {\n mstore(dest, mload(src))\n }\n dest += 32;\n src += 32;\n }\n\n uint256 mask;\n unchecked {\n mask = 256**(32 - len) - 1;\n }\n assembly {\n let srcpart := and(mload(src), not(mask))\n let destpart := and(mload(dest), mask)\n mstore(dest, or(destpart, srcpart))\n }\n }\n\n /**\n * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\n * @notice Flattens a list of byte strings into one byte string.\n *\n * @param _list List of byte strings to flatten.\n *\n * @return The flattened byte string.\n */\n function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\n if (_list.length == 0) {\n return new bytes(0);\n }\n\n uint256 len;\n uint256 i = 0;\n for (; i < _list.length; i++) {\n len += _list[i].length;\n }\n\n bytes memory flattened = new bytes(len);\n uint256 flattenedPtr;\n assembly {\n flattenedPtr := add(flattened, 0x20)\n }\n\n for (i = 0; i < _list.length; i++) {\n bytes memory item = _list[i];\n\n uint256 listPtr;\n assembly {\n listPtr := add(item, 0x20)\n }\n\n _memcpy(flattenedPtr, listPtr, item.length);\n flattenedPtr += _list[i].length;\n }\n\n return flattened;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" + }, + "contracts/universal/op-erc721/IOptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n IERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\";\n\n/**\n * @title IOptimismMintableERC721\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\n */\ninterface IOptimismMintableERC721 is IERC721Enumerable {\n /**\n * @notice Emitted when a token is minted.\n *\n * @param account Address of the account the token was minted to.\n * @param tokenId Token ID of the minted token.\n */\n event Mint(address indexed account, uint256 tokenId);\n\n /**\n * @notice Emitted when a token is burned.\n *\n * @param account Address of the account the token was burned from.\n * @param tokenId Token ID of the burned token.\n */\n event Burn(address indexed account, uint256 tokenId);\n\n /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function remoteChainId() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function remoteToken() external view returns (address);\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n function bridge() external view returns (address);\n\n /**\n * @notice Mints some token ID for a user, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * @param _to Address of the user to mint the token for.\n * @param _tokenId Token ID to mint.\n */\n function safeMint(address _to, uint256 _tokenId) external;\n\n /**\n * @notice Burns a token ID from a user.\n *\n * @param _from Address of the user to burn the token from.\n * @param _tokenId Token ID to burn.\n */\n function burn(address _from, uint256 _tokenId) external;\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n /**\n * @dev Returns the total amount of tokens stored by the contract.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n /**\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n * Use along with {totalSupply} to enumerate all tokens.\n */\n function tokenByIndex(uint256 index) external view returns (uint256);\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismMintableERC721 } from \"./OptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC721Factory\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\n */\ncontract OptimismMintableERC721Factory is Semver {\n /**\n * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\n *\n * @param localToken Address of the token on the this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param deployer Address of the initiator of the deployment\n */\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n address public immutable bridge;\n\n /**\n * @notice Chain ID for the remote network.\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 0, 0) {\n require(\n _bridge != address(0),\n \"OptimismMintableERC721Factory: bridge cannot be address(0)\"\n );\n require(\n _remoteChainId != 0,\n \"OptimismMintableERC721Factory: remote chain id cannot be zero\"\n );\n\n bridge = _bridge;\n remoteChainId = _remoteChainId;\n }\n\n /**\n * @notice Creates an instance of the standard ERC721.\n *\n * @param _remoteToken Address of the corresponding token on the other domain.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n function createOptimismMintableERC721(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721Factory: L1 token address cannot be address(0)\"\n );\n\n address localToken = address(\n new OptimismMintableERC721(bridge, remoteChainId, _remoteToken, _name, _symbol)\n );\n\n isOptimismMintableERC721[localToken] = true;\n emit OptimismMintableERC721Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n ERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { IOptimismMintableERC721 } from \"./IOptimismMintableERC721.sol\";\n\n/**\n * @title OptimismMintableERC721\n * @notice This contract is the remote representation for some token that lives on another network,\n * typically an Optimism representation of an Ethereum-based token. Standard reference\n * implementation that can be extended or modified according to your needs.\n */\ncontract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable remoteToken;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable bridge;\n\n /**\n * @notice Base token URI for this token.\n */\n string public baseTokenURI;\n\n /**\n * @param _bridge Address of the bridge on this network.\n * @param _remoteChainId Chain ID where the remote token is deployed.\n * @param _remoteToken Address of the corresponding token on the other network.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n constructor(\n address _bridge,\n uint256 _remoteChainId,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC721(_name, _symbol) {\n require(_bridge != address(0), \"OptimismMintableERC721: bridge cannot be address(0)\");\n require(_remoteChainId != 0, \"OptimismMintableERC721: remote chain id cannot be zero\");\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721: remote token cannot be address(0)\"\n );\n\n remoteChainId = _remoteChainId;\n remoteToken = _remoteToken;\n bridge = _bridge;\n\n // Creates a base URI in the format specified by EIP-681:\n // https://eips.ethereum.org/EIPS/eip-681\n baseTokenURI = string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(_remoteToken), 20),\n \"@\",\n Strings.toString(_remoteChainId),\n \"/tokenURI?uint256=\"\n )\n );\n }\n\n /**\n * @notice Modifier that prevents callers other than the bridge from calling the function.\n */\n modifier onlyBridge() {\n require(msg.sender == bridge, \"OptimismMintableERC721: only bridge can call this function\");\n _;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {\n _safeMint(_to, _tokenId);\n\n emit Mint(_to, _tokenId);\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function burn(address _from, uint256 _tokenId) external virtual onlyBridge {\n _burn(_tokenId);\n\n emit Burn(_from, _tokenId);\n }\n\n /**\n * @notice Checks if a given interface ID is supported by this contract.\n *\n * @param _interfaceId The interface ID to check.\n *\n * @return True if the interface ID is supported, false otherwise.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n override(ERC721Enumerable, IERC165)\n returns (bool)\n {\n bytes4 iface1 = type(IERC165).interfaceId;\n bytes4 iface2 = type(IOptimismMintableERC721).interfaceId;\n return\n _interfaceId == iface1 ||\n _interfaceId == iface2 ||\n super.supportsInterface(_interfaceId);\n }\n\n /**\n * @notice Returns the base token URI.\n *\n * @return Base token URI.\n */\n function _baseURI() internal view virtual override returns (string memory) {\n return baseTokenURI;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721.sol\";\nimport \"./IERC721Enumerable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\n // Mapping from owner to list of owned token IDs\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n // Mapping from token ID to index of the owner tokens list\n mapping(uint256 => uint256) private _ownedTokensIndex;\n\n // Array with all token ids, used for enumeration\n uint256[] private _allTokens;\n\n // Mapping from token id to position in the allTokens array\n mapping(uint256 => uint256) private _allTokensIndex;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721.balanceOf(owner), \"ERC721Enumerable: owner index out of bounds\");\n return _ownedTokens[owner][index];\n }\n\n /**\n * @dev See {IERC721Enumerable-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _allTokens.length;\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenByIndex}.\n */\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721Enumerable.totalSupply(), \"ERC721Enumerable: global index out of bounds\");\n return _allTokens[index];\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, tokenId);\n\n if (from == address(0)) {\n _addTokenToAllTokensEnumeration(tokenId);\n } else if (from != to) {\n _removeTokenFromOwnerEnumeration(from, tokenId);\n }\n if (to == address(0)) {\n _removeTokenFromAllTokensEnumeration(tokenId);\n } else if (to != from) {\n _addTokenToOwnerEnumeration(to, tokenId);\n }\n }\n\n /**\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\n * @param to address representing the new owner of the given token ID\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n */\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n uint256 length = ERC721.balanceOf(to);\n _ownedTokens[to][length] = tokenId;\n _ownedTokensIndex[tokenId] = length;\n }\n\n /**\n * @dev Private function to add a token to this extension's token tracking data structures.\n * @param tokenId uint256 ID of the token to be added to the tokens list\n */\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n _allTokensIndex[tokenId] = _allTokens.length;\n _allTokens.push(tokenId);\n }\n\n /**\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n * @param from address representing the previous owner of the given token ID\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n */\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary\n if (tokenIndex != lastTokenIndex) {\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\n\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n }\n\n // This also deletes the contents at the last position of the array\n delete _ownedTokensIndex[tokenId];\n delete _ownedTokens[from][lastTokenIndex];\n }\n\n /**\n * @dev Private function to remove a token from this extension's token tracking data structures.\n * This has O(1) time complexity, but alters the order of the _allTokens array.\n * @param tokenId uint256 ID of the token to be removed from the tokens list\n */\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = _allTokens.length - 1;\n uint256 tokenIndex = _allTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n uint256 lastTokenId = _allTokens[lastTokenIndex];\n\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n // This also deletes the contents at the last position of the array\n delete _allTokensIndex[tokenId];\n _allTokens.pop();\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: balance query for the zero address\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _owners[tokenId];\n require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not owner nor approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n _safeTransfer(from, to, tokenId, _data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _owners[tokenId] != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, _data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId);\n\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId);\n\n // Clear approvals\n _approve(address(0), tokenId);\n\n _balances[owner] -= 1;\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId);\n\n // Clear approvals from the previous owner\n _approve(address(0), tokenId);\n\n _balances[from] -= 1;\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits a {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/AddressManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:legacy\n * @title AddressManager\n * @notice AddressManager is a legacy contract that was used in the old version of the Optimism\n * system to manage a registry of string names to addresses. We now use a more standard\n * proxy system instead, but this contract is still necessary for backwards compatibility\n * with several older contracts.\n */\ncontract AddressManager is Ownable {\n /**\n * @notice Mapping of the hashes of string names to addresses.\n */\n mapping(bytes32 => address) private addresses;\n\n /**\n * @notice Emitted when an address is modified in the registry.\n *\n * @param name String name being set in the registry.\n * @param newAddress Address set for the given name.\n * @param oldAddress Address that was previously set for the given name.\n */\n event AddressSet(string indexed name, address newAddress, address oldAddress);\n\n /**\n * @notice Changes the address associated with a particular name.\n *\n * @param _name String name to associate an address with.\n * @param _address Address to associate with the name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n bytes32 nameHash = _getNameHash(_name);\n address oldAddress = addresses[nameHash];\n addresses[nameHash] = _address;\n\n emit AddressSet(_name, _address, oldAddress);\n }\n\n /**\n * @notice Retrieves the address associated with a given name.\n *\n * @param _name Name to retrieve an address for.\n *\n * @return Address associated with the given name.\n */\n function getAddress(string memory _name) external view returns (address) {\n return addresses[_getNameHash(_name)];\n }\n\n /**\n * @notice Computes the hash of a name.\n *\n * @param _name Name to compute a hash for.\n *\n * @return Hash of the given name.\n */\n function _getNameHash(string memory _name) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(_name));\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\nimport { Proxy } from \"./Proxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\n\n/**\n * @title IStaticERC1967Proxy\n * @notice IStaticERC1967Proxy is a static version of the ERC1967 proxy interface.\n */\ninterface IStaticERC1967Proxy {\n function implementation() external view returns (address);\n\n function admin() external view returns (address);\n}\n\n/**\n * @title IStaticL1ChugSplashProxy\n * @notice IStaticL1ChugSplashProxy is a static version of the ChugSplash proxy interface.\n */\ninterface IStaticL1ChugSplashProxy {\n function getImplementation() external view returns (address);\n\n function getOwner() external view returns (address);\n}\n\n/**\n * @title ProxyAdmin\n * @notice This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy,\n * based on the OpenZeppelin implementation. It has backwards compatibility logic to work\n * with the various types of proxies that have been deployed by Optimism in the past.\n */\ncontract ProxyAdmin is Owned {\n /**\n * @notice The proxy types that the ProxyAdmin can manage.\n *\n * @custom:value ERC1967 Represents an ERC1967 compliant transparent proxy interface.\n * @custom:value CHUGSPLASH Represents the Chugsplash proxy interface (legacy).\n * @custom:value RESOLVED Represents the ResolvedDelegate proxy (legacy).\n */\n enum ProxyType {\n ERC1967,\n CHUGSPLASH,\n RESOLVED\n }\n\n /**\n * @custom:legacy\n * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\n * @custom:legacy\n * @notice A reverse mapping of addresses to names held in the AddressManager. This must be\n * manually kept up to date with changes in the AddressManager for this contract\n * to be able to work as an admin for the ResolvedDelegateProxy type.\n */\n mapping(address => string) public implementationName;\n\n /**\n * @custom:legacy\n * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @custom:legacy\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading = false;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * @notice Sets the proxy type for a given address. Only required for non-standard (legacy)\n * proxy types.\n *\n * @param _address Address of the proxy.\n * @param _type Type of the proxy.\n */\n function setProxyType(address _address, ProxyType _type) external onlyOwner {\n proxyType[_address] = _type;\n }\n\n /**\n * @notice Sets the implementation name for a given address. Only required for\n * ResolvedDelegateProxy type proxies that have an implementation name.\n *\n * @param _address Address of the ResolvedDelegateProxy.\n * @param _name Name of the implementation for the proxy.\n */\n function setImplementationName(address _address, string memory _name) external onlyOwner {\n implementationName[_address] = _name;\n }\n\n /**\n * @notice Set the address of the AddressManager. This is required to manage legacy\n * ResolvedDelegateProxy type proxy contracts.\n *\n * @param _address Address of the AddressManager.\n */\n function setAddressManager(AddressManager _address) external onlyOwner {\n addressManager = _address;\n }\n\n /**\n * @custom:legacy\n * @notice Set an address in the address manager. Since only the owner of the AddressManager\n * can directly modify addresses and the ProxyAdmin will own the AddressManager, this\n * gives the owner of the ProxyAdmin the ability to modify addresses directly.\n *\n * @param _name Name to set within the AddressManager.\n * @param _address Address to attach to the given name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n addressManager.setAddress(_name, _address);\n }\n\n /**\n * @custom:legacy\n * @notice Set the upgrading status for the Chugsplash proxy type.\n *\n * @param _upgrading Whether or not the system is upgrading.\n */\n function setUpgrading(bool _upgrading) external onlyOwner {\n upgrading = _upgrading;\n }\n\n /**\n * @notice Updates the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to update.\n * @param _newAdmin Address of the new proxy admin.\n */\n function changeProxyAdmin(address payable _proxy, address _newAdmin) external onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).changeAdmin(_newAdmin);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setOwner(_newAdmin);\n } else if (ptype == ProxyType.RESOLVED) {\n addressManager.transferOwnership(_newAdmin);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract and delegatecalls the new implementation\n * with some given data. Useful for atomic upgrade-and-initialize calls.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n * @param _data Data to trigger the new implementation with.\n */\n function upgradeAndCall(\n address payable _proxy,\n address _implementation,\n bytes memory _data\n ) external payable onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeToAndCall{ value: msg.value }(_implementation, _data);\n } else {\n // reverts if proxy type is unknown\n upgrade(_proxy, _implementation);\n (bool success, ) = _proxy.call{ value: msg.value }(_data);\n require(success, \"ProxyAdmin: call to proxy after upgrade failed\");\n }\n }\n\n /**\n * @custom:legacy\n * @notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\n *\n * @return Whether or not there is an upgrade going on. May not actually tell you whether an\n * upgrade is going on, since we don't currently plan to use this variable for anything\n * other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\n */\n function isUpgrading() external view returns (bool) {\n return upgrading;\n }\n\n /**\n * @notice Returns the implementation of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the implementation of.\n *\n * @return Address of the implementation of the proxy.\n */\n function getProxyImplementation(address _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).implementation();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getImplementation();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.getAddress(implementationName[_proxy]);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Returns the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the admin of.\n *\n * @return Address of the admin of the proxy.\n */\n function getProxyAdmin(address payable _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).admin();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getOwner();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.owner();\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n */\n function upgrade(address payable _proxy, address _implementation) public onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeTo(_implementation);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setStorage(\n // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,\n bytes32(uint256(uint160(_implementation)))\n );\n } else if (ptype == ProxyType.RESOLVED) {\n string memory name = implementationName[_proxy];\n addressManager.setAddress(name, _implementation);\n } else {\n // It should not be possible to retrieve a ProxyType value which is not matched by\n // one of the previous conditions.\n assert(false);\n }\n }\n}\n" + }, + "@rari-capital/solmate/src/auth/Owned.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol)\nabstract contract Owned {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event OwnerUpdated(address indexed user, address indexed newOwner);\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP STORAGE\n //////////////////////////////////////////////////////////////*/\n\n address public owner;\n\n modifier onlyOwner() virtual {\n require(msg.sender == owner, \"UNAUTHORIZED\");\n\n _;\n }\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(address _owner) {\n owner = _owner;\n\n emit OwnerUpdated(address(0), _owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function setOwner(address newOwner) public virtual onlyOwner {\n owner = newOwner;\n\n emit OwnerUpdated(msg.sender, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Proxy\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\n * if the caller is address(0), meaning that the call originated from an off-chain\n * simulation.\n */\ncontract Proxy {\n /**\n * @notice The storage slot that holds the address of the implementation.\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice The storage slot that holds the address of the owner.\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice An event that is emitted each time the implementation is changed. This event is part\n * of the EIP-1967 specification.\n *\n * @param implementation The address of the implementation contract\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\n * EIP-1967 specification.\n *\n * @param previousAdmin The previous owner of the contract\n * @param newAdmin The new owner of the contract\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\n * eth_call to interact with this proxy without needing to use low-level storage\n * inspection. We assume that nobody is able to trigger calls from address(0) during\n * normal EVM execution.\n */\n modifier proxyCallIfNotAdmin() {\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\n * EIP-1967 admin storage slot so that accidental storage collision with the\n * implementation is not possible.\n *\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\n * transparent proxy interface.\n */\n constructor(address _admin) {\n _changeAdmin(_admin);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Set the implementation contract address. The code at the given address will execute\n * when this contract is called.\n *\n * @param _implementation Address of the implementation contract.\n */\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\n _setImplementation(_implementation);\n }\n\n /**\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\n * atomic execution of initialization-based upgrades.\n *\n * @param _implementation Address of the implementation contract.\n * @param _data Calldata to delegatecall the new implementation with.\n */\n function upgradeToAndCall(address _implementation, bytes calldata _data)\n external\n payable\n proxyCallIfNotAdmin\n returns (bytes memory)\n {\n _setImplementation(_implementation);\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\n require(success, \"Proxy: delegatecall to new implementation contract failed\");\n return returndata;\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _admin New owner of the proxy contract.\n */\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\n _changeAdmin(_admin);\n }\n\n /**\n * @notice Gets the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function admin() external proxyCallIfNotAdmin returns (address) {\n return _getAdmin();\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function implementation() external proxyCallIfNotAdmin returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n emit Upgraded(_implementation);\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _admin New owner of the proxy contract.\n */\n function _changeAdmin(address _admin) internal {\n address previous = _getAdmin();\n assembly {\n sstore(OWNER_KEY, _admin)\n }\n emit AdminChanged(previous, _admin);\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal {\n address impl = _getImplementation();\n require(impl != address(0), \"Proxy: implementation not initialized\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address impl;\n assembly {\n impl := sload(IMPLEMENTATION_KEY)\n }\n return impl;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getAdmin() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/L1ChugSplashProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title IL1ChugSplashDeployer\n */\ninterface IL1ChugSplashDeployer {\n function isUpgrading() external view returns (bool);\n}\n\n/**\n * @custom:legacy\n * @title L1ChugSplashProxy\n * @notice Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added\n * functions `setCode` and `setStorage` for changing the code or storage of the contract.\n *\n * Note for future developers: do NOT make anything in this contract 'public' unless you\n * know what you're doing. Anything public can potentially have a function signature that\n * conflicts with a signature attached to the implementation contract. Public functions\n * SHOULD always have the `proxyCallIfNotOwner` modifier unless there's some *really* good\n * reason not to have that modifier. And there almost certainly is not a good reason to not\n * have that modifier. Beware!\n */\ncontract L1ChugSplashProxy {\n /**\n * @notice \"Magic\" prefix. When prepended to some arbitrary bytecode and used to create a\n * contract, the appended bytecode will be deployed as given.\n */\n bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice Blocks a function from being called when the parent signals that the system should\n * be paused via an isUpgrading function.\n */\n modifier onlyWhenNotPaused() {\n address owner = _getOwner();\n\n // We do a low-level call because there's no guarantee that the owner actually *is* an\n // L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and\n // it turns out that it isn't the right type of contract.\n (bool success, bytes memory returndata) = owner.staticcall(\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector)\n );\n\n // If the call was unsuccessful then we assume that there's no \"isUpgrading\" method and we\n // can just continue as normal. We also expect that the return value is exactly 32 bytes\n // long. If this isn't the case then we can safely ignore the result.\n if (success && returndata.length == 32) {\n // Although the expected value is a *boolean*, it's safer to decode as a uint256 in the\n // case that the isUpgrading function returned something other than 0 or 1. But we only\n // really care about the case where this value is 0 (= false).\n uint256 ret = abi.decode(returndata, (uint256));\n require(ret == 0, \"L1ChugSplashProxy: system is currently being upgraded\");\n }\n\n _;\n }\n\n /**\n * @notice Makes a proxy call instead of triggering the given function when the caller is\n * either the owner or the zero address. Caller can only ever be the zero address if\n * this function is being called off-chain via eth_call, which is totally fine and can\n * be convenient for client-side tooling. Avoids situations where the proxy and\n * implementation share a sighash and the proxy function ends up being called instead\n * of the implementation one.\n *\n * Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If\n * there's a way for someone to send a transaction with msg.sender == address(0) in any\n * real context then we have much bigger problems. Primary reason to include this\n * additional allowed sender is because the owner address can be changed dynamically\n * and we do not want clients to have to keep track of the current owner in order to\n * make an eth_call that doesn't trigger the proxied contract.\n */\n // slither-disable-next-line incorrect-modifier\n modifier proxyCallIfNotOwner() {\n if (msg.sender == _getOwner() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @param _owner Address of the initial contract owner.\n */\n constructor(address _owner) {\n _setOwner(_owner);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Sets the code that should be running behind this proxy.\n *\n * Note: This scheme is a bit different from the standard proxy scheme where one would\n * typically deploy the code separately and then set the implementation address. We're\n * doing it this way because it gives us a lot more freedom on the client side. Can\n * only be triggered by the contract owner.\n *\n * @param _code New contract code to run inside this contract.\n */\n function setCode(bytes memory _code) external proxyCallIfNotOwner {\n // Get the code hash of the current implementation.\n address implementation = _getImplementation();\n\n // If the code hash matches the new implementation then we return early.\n if (keccak256(_code) == _getAccountCodeHash(implementation)) {\n return;\n }\n\n // Create the deploycode by appending the magic prefix.\n bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code);\n\n // Deploy the code and set the new implementation address.\n address newImplementation;\n assembly {\n newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode))\n }\n\n // Check that the code was actually deployed correctly. I'm not sure if you can ever\n // actually fail this check. Should only happen if the contract creation from above runs\n // out of gas but this parent execution thread does NOT run out of gas. Seems like we\n // should be doing this check anyway though.\n require(\n _getAccountCodeHash(newImplementation) == keccak256(_code),\n \"L1ChugSplashProxy: code was not correctly deployed\"\n );\n\n _setImplementation(newImplementation);\n }\n\n /**\n * @notice Modifies some storage slot within the proxy contract. Gives us a lot of power to\n * perform upgrades in a more transparent way. Only callable by the owner.\n *\n * @param _key Storage key to modify.\n * @param _value New value for the storage key.\n */\n function setStorage(bytes32 _key, bytes32 _value) external proxyCallIfNotOwner {\n assembly {\n sstore(_key, _value)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _owner New owner of the proxy contract.\n */\n function setOwner(address _owner) external proxyCallIfNotOwner {\n _setOwner(_owner);\n }\n\n /**\n * @notice Queries the owner of the proxy contract. Can only be called by the owner OR by\n * making an eth_call and setting the \"from\" address to address(0).\n *\n * @return Owner address.\n */\n function getOwner() external proxyCallIfNotOwner returns (address) {\n return _getOwner();\n }\n\n /**\n * @notice Queries the implementation address. Can only be called by the owner OR by making an\n * eth_call and setting the \"from\" address to address(0).\n *\n * @return Implementation address.\n */\n function getImplementation() external proxyCallIfNotOwner returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _owner New owner of the proxy contract.\n */\n function _setOwner(address _owner) internal {\n assembly {\n sstore(OWNER_KEY, _owner)\n }\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal onlyWhenNotPaused {\n address implementation = _getImplementation();\n\n require(implementation != address(0), \"L1ChugSplashProxy: implementation is not set yet\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address implementation;\n assembly {\n implementation := sload(IMPLEMENTATION_KEY)\n }\n return implementation;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getOwner() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n\n /**\n * @notice Gets the code hash for a given account.\n *\n * @param _account Address of the account to get a code hash for.\n *\n * @return Code hash for the account.\n */\n function _getAccountCodeHash(address _account) internal view returns (bytes32) {\n bytes32 codeHash;\n assembly {\n codeHash := extcodehash(_account)\n }\n return codeHash;\n }\n}\n" + }, + "contracts/testing/helpers/ExternalContractCompiler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ProxyAdmin } from \"@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol\";\nimport { Proxy } from \"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\";\n\n/**\n * Just exists so we can compile external contracts.\n */\ncontract ExternalContractCompiler {\n\n}\n" + }, + "contracts/testing/helpers/TestERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\n\ncontract TestERC721 is ERC721 {\n constructor() ERC721(\"TEST\", \"TST\") {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n\n function tokenURI(uint256) public pure virtual override returns (string memory) {}\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 indexed id);\n\n event Approval(address indexed owner, address indexed spender, uint256 indexed id);\n\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE/LOGIC\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n function tokenURI(uint256 id) public view virtual returns (string memory);\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) internal _ownerOf;\n\n mapping(address => uint256) internal _balanceOf;\n\n function ownerOf(uint256 id) public view virtual returns (address owner) {\n require((owner = _ownerOf[id]) != address(0), \"NOT_MINTED\");\n }\n\n function balanceOf(address owner) public view virtual returns (uint256) {\n require(owner != address(0), \"ZERO_ADDRESS\");\n\n return _balanceOf[owner];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) public getApproved;\n\n mapping(address => mapping(address => bool)) public isApprovedForAll;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(string memory _name, string memory _symbol) {\n name = _name;\n symbol = _symbol;\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 id) public virtual {\n address owner = _ownerOf[id];\n\n require(msg.sender == owner || isApprovedForAll[owner][msg.sender], \"NOT_AUTHORIZED\");\n\n getApproved[id] = spender;\n\n emit Approval(owner, spender, id);\n }\n\n function setApprovalForAll(address operator, bool approved) public virtual {\n isApprovedForAll[msg.sender][operator] = approved;\n\n emit ApprovalForAll(msg.sender, operator, approved);\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n require(from == _ownerOf[id], \"WRONG_FROM\");\n\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(\n msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],\n \"NOT_AUTHORIZED\"\n );\n\n // Underflow of the sender's balance is impossible because we check for\n // ownership above and the recipient's balance can't realistically overflow.\n unchecked {\n _balanceOf[from]--;\n\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n delete getApproved[id];\n\n emit Transfer(from, to, id);\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n bytes calldata data\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return\n interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165\n interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721\n interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 id) internal virtual {\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(_ownerOf[id] == address(0), \"ALREADY_MINTED\");\n\n // Counter overflow is incredibly unrealistic.\n unchecked {\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n emit Transfer(address(0), to, id);\n }\n\n function _burn(uint256 id) internal virtual {\n address owner = _ownerOf[id];\n\n require(owner != address(0), \"NOT_MINTED\");\n\n // Ownership check above ensures no underflow.\n unchecked {\n _balanceOf[owner]--;\n }\n\n delete _ownerOf[id];\n\n delete getApproved[id];\n\n emit Transfer(owner, address(0), id);\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL SAFE MINT LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _safeMint(address to, uint256 id) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function _safeMint(\n address to,\n uint256 id,\n bytes memory data\n ) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n}\n\n/// @notice A generic interface for a contract which properly accepts ERC721 tokens.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721TokenReceiver {\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n ) external virtual returns (bytes4) {\n return ERC721TokenReceiver.onERC721Received.selector;\n }\n}\n" + }, + "contracts/testing/helpers/TestERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n constructor() ERC20(\"TEST\", \"TST\", 18) {}\n\n function mint(address to, uint256 value) public {\n _mint(to, value);\n }\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "contracts/L1/TeleportrWithdrawer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AssetReceiver } from \"../universal/AssetReceiver.sol\";\n\n/**\n * @notice Stub interface for Teleportr.\n */\ninterface Teleportr {\n function withdrawBalance() external;\n}\n\n/**\n * @title TeleportrWithdrawer\n * @notice The TeleportrWithdrawer is a simple contract capable of withdrawing funds from the\n * TeleportrContract and sending them to some recipient address.\n */\ncontract TeleportrWithdrawer is AssetReceiver {\n /**\n * @notice Address of the Teleportr contract.\n */\n address public teleportr;\n\n /**\n * @notice Address that will receive Teleportr withdrawals.\n */\n address public recipient;\n\n /**\n * @notice Data to be sent to the recipient address.\n */\n bytes public data;\n\n /**\n * @param _owner Initial owner of the contract.\n */\n constructor(address _owner) AssetReceiver(_owner) {}\n\n /**\n * @notice Allows the owner to update the recipient address.\n *\n * @param _recipient New recipient address.\n */\n function setRecipient(address _recipient) external onlyOwner {\n recipient = _recipient;\n }\n\n /**\n * @notice Allows the owner to update the Teleportr contract address.\n *\n * @param _teleportr New Teleportr contract address.\n */\n function setTeleportr(address _teleportr) external onlyOwner {\n teleportr = _teleportr;\n }\n\n /**\n * @notice Allows the owner to update the data to be sent to the recipient address.\n *\n * @param _data New data to be sent to the recipient address.\n */\n function setData(bytes memory _data) external onlyOwner {\n data = _data;\n }\n\n /**\n * @notice Withdraws the full balance of the Teleportr contract to the recipient address.\n * Anyone is allowed to trigger this function since the recipient address cannot be\n * controlled by the msg.sender.\n */\n function withdrawFromTeleportr() external {\n Teleportr(teleportr).withdrawBalance();\n (bool success, ) = recipient.call{ value: address(this).balance }(data);\n require(success, \"TeleportrWithdrawer: send failed\");\n }\n}\n" + }, + "contracts/universal/AssetReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\nimport { Transactor } from \"./Transactor.sol\";\n\n/**\n * @title AssetReceiver\n * @notice AssetReceiver is a minimal contract for receiving funds assets in the form of either\n * ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.\n */\ncontract AssetReceiver is Transactor {\n /**\n * @notice Emitted when ETH is received by this address.\n *\n * @param from Address that sent ETH to this contract.\n * @param amount Amount of ETH received.\n */\n event ReceivedETH(address indexed from, uint256 amount);\n\n /**\n * @notice Emitted when ETH is withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param amount ETH amount withdrawn.\n */\n event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param amount ERC20 amount withdrawn.\n */\n event WithdrewERC20(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 amount\n );\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param id Token ID being withdrawn.\n */\n event WithdrewERC721(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 id\n );\n\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Transactor(_owner) {}\n\n /**\n * @notice Make sure we can receive ETH.\n */\n receive() external payable {\n emit ReceivedETH(msg.sender, msg.value);\n }\n\n /**\n * @notice Withdraws full ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n */\n function withdrawETH(address payable _to) external onlyOwner {\n withdrawETH(_to, address(this).balance);\n }\n\n /**\n * @notice Withdraws partial ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n * @param _amount Amount of ETH to withdraw.\n */\n function withdrawETH(address payable _to, uint256 _amount) public onlyOwner {\n // slither-disable-next-line reentrancy-unlimited-gas\n (bool success, ) = _to.call{ value: _amount }(\"\");\n emit WithdrewETH(msg.sender, _to, _amount);\n }\n\n /**\n * @notice Withdraws full ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n */\n function withdrawERC20(ERC20 _asset, address _to) external onlyOwner {\n withdrawERC20(_asset, _to, _asset.balanceOf(address(this)));\n }\n\n /**\n * @notice Withdraws partial ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n * @param _amount Amount of ERC20 to withdraw.\n */\n function withdrawERC20(\n ERC20 _asset,\n address _to,\n uint256 _amount\n ) public onlyOwner {\n // slither-disable-next-line unchecked-transfer\n _asset.transfer(_to, _amount);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC20(msg.sender, _to, address(_asset), _amount);\n }\n\n /**\n * @notice Withdraws ERC721 token to the recipient.\n *\n * @param _asset ERC721 token to withdraw.\n * @param _to Address to receive the ERC721 token.\n * @param _id Token ID of the ERC721 token to withdraw.\n */\n function withdrawERC721(\n ERC721 _asset,\n address _to,\n uint256 _id\n ) external onlyOwner {\n _asset.transferFrom(address(this), _to, _id);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC721(msg.sender, _to, address(_asset), _id);\n }\n}\n" + }, + "contracts/universal/Transactor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\n\n/**\n * @title Transactor\n * @notice Transactor is a minimal contract that can send transactions.\n */\ncontract Transactor is Owned {\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * Sends a CALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n * @param _value ETH value to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function CALL(\n address _target,\n bytes memory _data,\n uint256 _value\n ) external payable onlyOwner returns (bool, bytes memory) {\n return _target.call{ value: _value }(_data);\n }\n\n /**\n * Sends a DELEGATECALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function DELEGATECALL(address _target, bytes memory _data)\n external\n payable\n onlyOwner\n returns (bool, bytes memory)\n {\n // slither-disable-next-line controlled-delegatecall\n return _target.delegatecall(_data);\n }\n}\n" + }, + "contracts/L2/TeleportrDisburser.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title TeleportrDisburser\n */\ncontract TeleportrDisburser is Ownable {\n /**\n * @notice A struct holding the address and amount to disbursement.\n */\n struct Disbursement {\n uint256 amount;\n address addr;\n }\n\n /**\n * @notice Total number of disbursements processed.\n */\n uint256 public totalDisbursements;\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a disbursement is successfuly sent.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The recipient of the disbursement.\n * @param amount The amount sent to the recipient.\n */\n event DisbursementSuccess(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @notice Emitted any time a disbursement fails to send.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The intended recipient of the disbursement.\n * @param amount The amount intended to be sent to the recipient.\n */\n event DisbursementFailed(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @custom:semver 0.0.1\n */\n constructor() {\n totalDisbursements = 0;\n }\n\n /**\n * @notice Accepts a list of Disbursements and forwards the amount paid to the contract to each\n * recipient. Reverts if there are zero disbursements, the total amount to forward\n * differs from the amount sent in the transaction, or the _nextDepositId is\n * unexpected. Failed disbursements will not cause the method to revert, but will\n * instead be held by the contract and available for the owner to withdraw.\n *\n * @param _nextDepositId The depositId of the first Dispursement.\n * @param _disbursements A list of Disbursements to process.\n */\n function disburse(uint256 _nextDepositId, Disbursement[] calldata _disbursements)\n external\n payable\n onlyOwner\n {\n // Ensure there are disbursements to process.\n uint256 _numDisbursements = _disbursements.length;\n require(_numDisbursements > 0, \"No disbursements\");\n\n // Ensure the _nextDepositId matches our expected value.\n uint256 _depositId = totalDisbursements;\n require(_depositId == _nextDepositId, \"Unexpected next deposit id\");\n unchecked {\n totalDisbursements += _numDisbursements;\n }\n\n // Ensure the amount sent in the transaction is equal to the sum of the\n // disbursements.\n uint256 _totalDisbursed = 0;\n for (uint256 i = 0; i < _numDisbursements; i++) {\n _totalDisbursed += _disbursements[i].amount;\n }\n require(_totalDisbursed == msg.value, \"Disbursement total != amount sent\");\n\n // Process disbursements.\n for (uint256 i = 0; i < _numDisbursements; i++) {\n uint256 _amount = _disbursements[i].amount;\n address _addr = _disbursements[i].addr;\n\n // Deliver the dispursement amount to the receiver. If the\n // disbursement fails, the amount will be kept by the contract\n // rather than reverting to prevent blocking progress on other\n // disbursements.\n\n // slither-disable-next-line calls-loop,reentrancy-events\n (bool success, ) = _addr.call{ value: _amount, gas: 2300 }(\"\");\n if (success) emit DisbursementSuccess(_depositId, _addr, _amount);\n else emit DisbursementFailed(_depositId, _addr, _amount);\n\n unchecked {\n _depositId += 1;\n }\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 balance = address(this).balance;\n emit BalanceWithdrawn(_owner, balance);\n payable(_owner).transfer(balance);\n }\n}\n" + }, + "contracts/L1/TeleportrDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:attribution https://github.com/0xclem/teleportr\n * @title TeleportrDeposit\n * @notice A contract meant to manage deposits into Optimism's Teleportr custodial bridge. Deposits\n * are rate limited to avoid a situation where too much ETH is flowing through this bridge\n * and cannot be properly disbursed on L2. Inspired by 0xclem's original Teleportr system\n * (https://github.com/0xclem/teleportr).\n */\ncontract TeleportrDeposit is Ownable {\n /**\n * @notice Minimum deposit amount (in wei).\n */\n uint256 public minDepositAmount;\n\n /**\n * @notice Maximum deposit amount (in wei).\n */\n uint256 public maxDepositAmount;\n\n /**\n * @notice Maximum balance this contract will hold before it starts rejecting deposits.\n */\n uint256 public maxBalance;\n\n /**\n * @notice Total number of deposits received.\n */\n uint256 public totalDeposits;\n\n /**\n * @notice Emitted any time the minimum deposit amount is set.\n *\n * @param previousAmount The previous minimum deposit amount.\n * @param newAmount The new minimum deposit amount.\n */\n event MinDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the maximum deposit amount is set.\n *\n * @param previousAmount The previous maximum deposit amount.\n * @param newAmount The new maximum deposit amount.\n */\n event MaxDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the contract maximum balance is set.\n *\n * @param previousBalance The previous maximum contract balance.\n * @param newBalance The new maximum contract balance.\n */\n event MaxBalanceSet(uint256 previousBalance, uint256 newBalance);\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a successful deposit is received.\n *\n * @param depositId A unique sequencer number identifying the deposit.\n * @param emitter The sending address of the payer.\n * @param amount The amount deposited by the payer.\n */\n event EtherReceived(uint256 indexed depositId, address indexed emitter, uint256 indexed amount);\n\n /**\n * @custom:semver 0.0.1\n *\n * @param _minDepositAmount The initial minimum deposit amount.\n * @param _maxDepositAmount The initial maximum deposit amount.\n * @param _maxBalance The initial maximum contract balance.\n */\n constructor(\n uint256 _minDepositAmount,\n uint256 _maxDepositAmount,\n uint256 _maxBalance\n ) {\n minDepositAmount = _minDepositAmount;\n maxDepositAmount = _maxDepositAmount;\n maxBalance = _maxBalance;\n totalDeposits = 0;\n emit MinDepositAmountSet(0, _minDepositAmount);\n emit MaxDepositAmountSet(0, _maxDepositAmount);\n emit MaxBalanceSet(0, _maxBalance);\n }\n\n /**\n * @notice Accepts deposits that will be disbursed to the sender's address on L2.\n */\n receive() external payable {\n require(msg.value >= minDepositAmount, \"Deposit amount is too small\");\n require(msg.value <= maxDepositAmount, \"Deposit amount is too big\");\n require(address(this).balance <= maxBalance, \"Contract max balance exceeded\");\n\n emit EtherReceived(totalDeposits, msg.sender, msg.value);\n unchecked {\n totalDeposits += 1;\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 _balance = address(this).balance;\n emit BalanceWithdrawn(_owner, _balance);\n payable(_owner).transfer(_balance);\n }\n\n /**\n * @notice Sets the minimum amount that can be deposited in a receive.\n *\n * @param _minDepositAmount The new minimum deposit amount.\n */\n function setMinAmount(uint256 _minDepositAmount) external onlyOwner {\n emit MinDepositAmountSet(minDepositAmount, _minDepositAmount);\n minDepositAmount = _minDepositAmount;\n }\n\n /**\n * @notice Sets the maximum amount that can be deposited in a receive.\n *\n * @param _maxDepositAmount The new maximum deposit amount.\n */\n function setMaxAmount(uint256 _maxDepositAmount) external onlyOwner {\n emit MaxDepositAmountSet(maxDepositAmount, _maxDepositAmount);\n maxDepositAmount = _maxDepositAmount;\n }\n\n /**\n * @notice Sets the maximum balance the contract can hold after a receive.\n *\n * @param _maxBalance The new maximum contract balance.\n */\n function setMaxBalance(uint256 _maxBalance) external onlyOwner {\n emit MaxBalanceSet(maxBalance, _maxBalance);\n maxBalance = _maxBalance;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/goerli/.chainId b/packages/contracts-periphery/deployments/goerli/.chainId new file mode 100644 index 0000000000000..7813681f5b41c --- /dev/null +++ b/packages/contracts-periphery/deployments/goerli/.chainId @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/goerli/L1ERC721Bridge.json b/packages/contracts-periphery/deployments/goerli/L1ERC721Bridge.json new file mode 100644 index 0000000000000..da422f0cbc51b --- /dev/null +++ b/packages/contracts-periphery/deployments/goerli/L1ERC721Bridge.json @@ -0,0 +1,457 @@ +{ + "address": "0x2fBFa09Db7f33b7a8fBCEEf80C75DA48E6B8c550", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_messenger", + "type": "address" + }, + { + "internalType": "address", + "name": "_otherBridge", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC721BridgeFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC721BridgeInitiated", + "type": "event" + }, + { + "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" + } + ], + "name": "bridgeERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "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" + } + ], + "name": "bridgeERC721To", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "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" + } + ], + "name": "finalizeBridgeERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "messenger", + "outputs": [ + { + "internalType": "contract CrossDomainMessenger", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "otherBridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x93f4f5f88b9c5461137ccb2c70867b79e5608710e6f3e4753474170c272e22b3", + "receipt": { + "to": null, + "from": "0x5c679a57e018F5F146838138d3E032Ef4913D551", + "contractAddress": "0x2fBFa09Db7f33b7a8fBCEEf80C75DA48E6B8c550", + "transactionIndex": 14, + "gasUsed": "1101007", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbf10078775cf36fcd03c1c37924579a9d45d916e9c1ed45106ef2482e168dc43", + "transactionHash": "0x93f4f5f88b9c5461137ccb2c70867b79e5608710e6f3e4753474170c272e22b3", + "logs": [], + "blockNumber": 7682781, + "cumulativeGasUsed": "3340767", + "status": 1, + "byzantium": true + }, + "args": [ + "0x5086d1eEF304eb5284A0f6720f79403b4e9bE294", + "0x4200000000000000000000000000000000000014" + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeInitiated\",\"type\":\"event\"},{\"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\"}],\"name\":\"bridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}],\"name\":\"bridgeERC721To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"finalizeBridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"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\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\",\"_otherBridge\":\"Address of the ERC721 bridge on the other 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.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"L1ERC721Bridge\",\"version\":1},\"userdoc\":{\"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.\"}},\"kind\":\"user\",\"methods\":{\"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.\"},\"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.\"},\"messenger()\":{\"notice\":\"Messenger contract on this domain.\"},\"otherBridge()\":{\"notice\":\"Address of the bridge on the other network.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"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.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1/L1ERC721Bridge.sol\":\"L1ERC721Bridge\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { Types } from \\\"./Types.sol\\\";\\nimport { Hashing } from \\\"./Hashing.sol\\\";\\nimport { RLPWriter } from \\\"./rlp/RLPWriter.sol\\\";\\n\\n/**\\n * @title Encoding\\n * @notice Encoding handles Optimism's various different encoding schemes.\\n */\\nlibrary Encoding {\\n /**\\n * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\\n * to the L2 system. Useful for searching for a deposit in the L2 system. The\\n * transaction is prefixed with 0x7e to identify its EIP-2718 type.\\n *\\n * @param _tx User deposit transaction to encode.\\n *\\n * @return RLP encoded L2 deposit transaction.\\n */\\n function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\\n internal\\n pure\\n returns (bytes memory)\\n {\\n bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\\n bytes[] memory raw = new bytes[](8);\\n raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\\n raw[1] = RLPWriter.writeAddress(_tx.from);\\n raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\\\"\\\") : RLPWriter.writeAddress(_tx.to);\\n raw[3] = RLPWriter.writeUint(_tx.mint);\\n raw[4] = RLPWriter.writeUint(_tx.value);\\n raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\\n raw[6] = RLPWriter.writeBool(false);\\n raw[7] = RLPWriter.writeBytes(_tx.data);\\n return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\\n }\\n\\n /**\\n * @notice Encodes the cross domain message based on the version that is encoded into the\\n * message nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes memory) {\\n (, uint16 version) = decodeVersionedNonce(_nonce);\\n if (version == 0) {\\n return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\\n } else if (version == 1) {\\n return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\\n } else {\\n revert(\\\"Encoding: unknown cross domain message version\\\");\\n }\\n }\\n\\n /**\\n * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\\n *\\n * @param _target Address of the target of the message.\\n * @param _sender Address of the sender of the message.\\n * @param _data Data to send with the message.\\n * @param _nonce Message nonce.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessageV0(\\n address _target,\\n address _sender,\\n bytes memory _data,\\n uint256 _nonce\\n ) internal pure returns (bytes memory) {\\n return\\n abi.encodeWithSignature(\\n \\\"relayMessage(address,address,bytes,uint256)\\\",\\n _target,\\n _sender,\\n _data,\\n _nonce\\n );\\n }\\n\\n /**\\n * @notice Encodes a cross domain message based on the V1 (current) encoding.\\n *\\n * @param _nonce Message nonce.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessageV1(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes memory) {\\n return\\n abi.encodeWithSignature(\\n \\\"relayMessage(uint256,address,address,uint256,uint256,bytes)\\\",\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _gasLimit,\\n _data\\n );\\n }\\n\\n /**\\n * @notice Adds a version number into the first two bytes of a message nonce.\\n *\\n * @param _nonce Message nonce to encode into.\\n * @param _version Version number to encode into the message nonce.\\n *\\n * @return Message nonce with version encoded into the first two bytes.\\n */\\n function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\\n uint256 nonce;\\n assembly {\\n nonce := or(shl(240, _version), _nonce)\\n }\\n return nonce;\\n }\\n\\n /**\\n * @notice Pulls the version out of a version-encoded nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n *\\n * @return Nonce without encoded version.\\n * @return Version of the message.\\n */\\n function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\\n uint240 nonce;\\n uint16 version;\\n assembly {\\n nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\\n version := shr(240, _nonce)\\n }\\n return (nonce, version);\\n }\\n}\\n\",\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { Types } from \\\"./Types.sol\\\";\\nimport { Encoding } from \\\"./Encoding.sol\\\";\\n\\n/**\\n * @title Hashing\\n * @notice Hashing handles Optimism's various different hashing schemes.\\n */\\nlibrary Hashing {\\n /**\\n * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\\n * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\\n * system.\\n *\\n * @param _tx User deposit transaction to hash.\\n *\\n * @return Hash of the RLP encoded L2 deposit transaction.\\n */\\n function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return keccak256(Encoding.encodeDepositTransaction(_tx));\\n }\\n\\n /**\\n * @notice Computes the deposit transaction's \\\"source hash\\\", a value that guarantees the hash\\n * of the L2 transaction that corresponds to a deposit is unique and is\\n * deterministically generated from L1 transaction data.\\n *\\n * @param _l1BlockHash Hash of the L1 block where the deposit was included.\\n * @param _logIndex The index of the log that created the deposit transaction.\\n *\\n * @return Hash of the deposit transaction's \\\"source hash\\\".\\n */\\n function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\\n internal\\n pure\\n returns (bytes32)\\n {\\n bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\\n return keccak256(abi.encode(bytes32(0), depositId));\\n }\\n\\n /**\\n * @notice Hashes the cross domain message based on the version that is encoded into the\\n * message nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes32) {\\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\\n if (version == 0) {\\n return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\\n } else if (version == 1) {\\n return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\\n } else {\\n revert(\\\"Hashing: unknown cross domain message version\\\");\\n }\\n }\\n\\n /**\\n * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\\n *\\n * @param _target Address of the target of the message.\\n * @param _sender Address of the sender of the message.\\n * @param _data Data to send with the message.\\n * @param _nonce Message nonce.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessageV0(\\n address _target,\\n address _sender,\\n bytes memory _data,\\n uint256 _nonce\\n ) internal pure returns (bytes32) {\\n return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\\n }\\n\\n /**\\n * @notice Hashes a cross domain message based on the V1 (current) encoding.\\n *\\n * @param _nonce Message nonce.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessageV1(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes32) {\\n return\\n keccak256(\\n Encoding.encodeCrossDomainMessageV1(\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _gasLimit,\\n _data\\n )\\n );\\n }\\n\\n /**\\n * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\\n *\\n * @param _tx Withdrawal transaction to hash.\\n *\\n * @return Hashed withdrawal transaction.\\n */\\n function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\\n );\\n }\\n\\n /**\\n * @notice Hashes the various elements of an output root proof into an output root hash which\\n * can be used to check if the proof is valid.\\n *\\n * @param _outputRootProof Output root proof which should hash to an output root.\\n *\\n * @return Hashed output root proof.\\n */\\n function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encode(\\n _outputRootProof.version,\\n _outputRootProof.stateRoot,\\n _outputRootProof.messagePasserStorageRoot,\\n _outputRootProof.latestBlockhash\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title SafeCall\\n * @notice Perform low level safe calls\\n */\\nlibrary SafeCall {\\n /**\\n * @notice Perform a low level call without copying any returndata\\n *\\n * @param _target Address to call\\n * @param _gas Amount of gas to pass to the call\\n * @param _value Amount of value to pass to the call\\n * @param _calldata Calldata to pass to the call\\n */\\n function call(\\n address _target,\\n uint256 _gas,\\n uint256 _value,\\n bytes memory _calldata\\n ) internal returns (bool) {\\n bool _success;\\n assembly {\\n _success := call(\\n _gas, // gas\\n _target, // recipient\\n _value, // ether value\\n add(_calldata, 0x20), // inloc\\n mload(_calldata), // inlen\\n 0, // outloc\\n 0 // outlen\\n )\\n }\\n return _success;\\n }\\n}\\n\",\"keccak256\":\"0xbb0621c028c18e9d5a54cf1a8136cf2e77f161de48aeb8d911e230f6b280c9ed\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Types\\n * @notice Contains various types used throughout the Optimism contract system.\\n */\\nlibrary Types {\\n /**\\n * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\\n * timestamp that the output root is posted. This timestamp is used to verify that the\\n * finalization period has passed since the output root was submitted.\\n */\\n struct OutputProposal {\\n bytes32 outputRoot;\\n uint256 timestamp;\\n }\\n\\n /**\\n * @notice Struct representing the elements that are hashed together to generate an output root\\n * which itself represents a snapshot of the L2 state.\\n */\\n struct OutputRootProof {\\n bytes32 version;\\n bytes32 stateRoot;\\n bytes32 messagePasserStorageRoot;\\n bytes32 latestBlockhash;\\n }\\n\\n /**\\n * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\\n * user (as opposed to a system deposit transaction generated by the system).\\n */\\n struct UserDepositTransaction {\\n address from;\\n address to;\\n bool isCreation;\\n uint256 value;\\n uint256 mint;\\n uint64 gasLimit;\\n bytes data;\\n bytes32 l1BlockHash;\\n uint256 logIndex;\\n }\\n\\n /**\\n * @notice Struct representing a withdrawal transaction.\\n */\\n struct WithdrawalTransaction {\\n uint256 nonce;\\n address sender;\\n address target;\\n uint256 value;\\n uint256 gasLimit;\\n bytes data;\\n }\\n}\\n\",\"keccak256\":\"0x69ca98e57a7cbe60cffeb0f76f6f9279010941b1931581e9a35478f30e2546d1\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\\n * @title RLPWriter\\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\\n * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\\n * modifications to improve legibility.\\n */\\nlibrary RLPWriter {\\n /**\\n * @notice RLP encodes a byte string.\\n *\\n * @param _in The byte string to encode.\\n *\\n * @return The RLP encoded string in bytes.\\n */\\n function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\\n bytes memory encoded;\\n\\n if (_in.length == 1 && uint8(_in[0]) < 128) {\\n encoded = _in;\\n } else {\\n encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\\n }\\n\\n return encoded;\\n }\\n\\n /**\\n * @notice RLP encodes a list of RLP encoded byte byte strings.\\n *\\n * @param _in The list of RLP encoded byte strings.\\n *\\n * @return The RLP encoded list of items in bytes.\\n */\\n function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\\n bytes memory list = _flatten(_in);\\n return abi.encodePacked(_writeLength(list.length, 192), list);\\n }\\n\\n /**\\n * @notice RLP encodes a string.\\n *\\n * @param _in The string to encode.\\n *\\n * @return The RLP encoded string in bytes.\\n */\\n function writeString(string memory _in) internal pure returns (bytes memory) {\\n return writeBytes(bytes(_in));\\n }\\n\\n /**\\n * @notice RLP encodes an address.\\n *\\n * @param _in The address to encode.\\n *\\n * @return The RLP encoded address in bytes.\\n */\\n function writeAddress(address _in) internal pure returns (bytes memory) {\\n return writeBytes(abi.encodePacked(_in));\\n }\\n\\n /**\\n * @notice RLP encodes a uint.\\n *\\n * @param _in The uint256 to encode.\\n *\\n * @return The RLP encoded uint256 in bytes.\\n */\\n function writeUint(uint256 _in) internal pure returns (bytes memory) {\\n return writeBytes(_toBinary(_in));\\n }\\n\\n /**\\n * @notice RLP encodes a bool.\\n *\\n * @param _in The bool to encode.\\n *\\n * @return The RLP encoded bool in bytes.\\n */\\n function writeBool(bool _in) internal pure returns (bytes memory) {\\n bytes memory encoded = new bytes(1);\\n encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\\n return encoded;\\n }\\n\\n /**\\n * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\\n *\\n * @param _len The length of the string or the payload.\\n * @param _offset 128 if item is string, 192 if item is list.\\n *\\n * @return RLP encoded bytes.\\n */\\n function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\\n bytes memory encoded;\\n\\n if (_len < 56) {\\n encoded = new bytes(1);\\n encoded[0] = bytes1(uint8(_len) + uint8(_offset));\\n } else {\\n uint256 lenLen;\\n uint256 i = 1;\\n while (_len / i != 0) {\\n lenLen++;\\n i *= 256;\\n }\\n\\n encoded = new bytes(lenLen + 1);\\n encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\\n for (i = 1; i <= lenLen; i++) {\\n encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\\n }\\n }\\n\\n return encoded;\\n }\\n\\n /**\\n * @notice Encode integer in big endian binary form with no leading zeroes.\\n *\\n * @param _x The integer to encode.\\n *\\n * @return RLP encoded bytes.\\n */\\n function _toBinary(uint256 _x) private pure returns (bytes memory) {\\n bytes memory b = abi.encodePacked(_x);\\n\\n uint256 i = 0;\\n for (; i < 32; i++) {\\n if (b[i] != 0) {\\n break;\\n }\\n }\\n\\n bytes memory res = new bytes(32 - i);\\n for (uint256 j = 0; j < res.length; j++) {\\n res[j] = b[i++];\\n }\\n\\n return res;\\n }\\n\\n /**\\n * @custom:attribution https://github.com/Arachnid/solidity-stringutils\\n * @notice Copies a piece of memory to another location.\\n *\\n * @param _dest Destination location.\\n * @param _src Source location.\\n * @param _len Length of memory to copy.\\n */\\n function _memcpy(\\n uint256 _dest,\\n uint256 _src,\\n uint256 _len\\n ) private pure {\\n uint256 dest = _dest;\\n uint256 src = _src;\\n uint256 len = _len;\\n\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n uint256 mask;\\n unchecked {\\n mask = 256**(32 - len) - 1;\\n }\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n\\n /**\\n * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\\n * @notice Flattens a list of byte strings into one byte string.\\n *\\n * @param _list List of byte strings to flatten.\\n *\\n * @return The flattened byte string.\\n */\\n function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\\n if (_list.length == 0) {\\n return new bytes(0);\\n }\\n\\n uint256 len;\\n uint256 i = 0;\\n for (; i < _list.length; i++) {\\n len += _list[i].length;\\n }\\n\\n bytes memory flattened = new bytes(len);\\n uint256 flattenedPtr;\\n assembly {\\n flattenedPtr := add(flattened, 0x20)\\n }\\n\\n for (i = 0; i < _list.length; i++) {\\n bytes memory item = _list[i];\\n\\n uint256 listPtr;\\n assembly {\\n listPtr := add(item, 0x20)\\n }\\n\\n _memcpy(flattenedPtr, listPtr, item.length);\\n flattenedPtr += _list[i].length;\\n }\\n\\n return flattened;\\n }\\n}\\n\",\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {\\n PausableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {\\n ReentrancyGuardUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeCall } from \\\"../libraries/SafeCall.sol\\\";\\nimport { Hashing } from \\\"../libraries/Hashing.sol\\\";\\nimport { Encoding } from \\\"../libraries/Encoding.sol\\\";\\n\\n/**\\n * @custom:legacy\\n * @title CrossDomainMessengerLegacySpacer\\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\\n * libAddressManager variable used to exist. Must be the first contract in the inheritance\\n * tree of the CrossDomainMessenger\\n */\\ncontract CrossDomainMessengerLegacySpacer {\\n /**\\n * @custom:legacy\\n * @custom:spacer libAddressManager\\n * @notice Spacer for backwards compatibility.\\n */\\n address private spacer_0_0_20;\\n}\\n\\n/**\\n * @custom:upgradeable\\n * @title CrossDomainMessenger\\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\\n * cross-chain messenger contracts. It's designed to be a universal interface that only\\n * needs to be extended slightly to provide low-level message passing functionality on each\\n * chain it's deployed on. Currently only designed for message passing between two paired\\n * chains and does not support one-to-many interactions.\\n */\\nabstract contract CrossDomainMessenger is\\n CrossDomainMessengerLegacySpacer,\\n OwnableUpgradeable,\\n PausableUpgradeable,\\n ReentrancyGuardUpgradeable\\n{\\n /**\\n * @notice Current message version identifier.\\n */\\n uint16 public constant MESSAGE_VERSION = 1;\\n\\n /**\\n * @notice Constant overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\\n\\n /**\\n * @notice Numerator for dynamic overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\\n\\n /**\\n * @notice Denominator for dynamic overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\\n\\n /**\\n * @notice Extra gas added to base gas for each byte of calldata in a message.\\n */\\n uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\\n\\n /**\\n * @notice Minimum amount of gas required to relay a message.\\n */\\n uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\\n\\n /**\\n * @notice Amount of gas held in reserve to guarantee that relay execution completes.\\n */\\n uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\\n\\n /**\\n * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\\n * because performing an SSTORE on a non-zero value is significantly cheaper than on a\\n * zero value.\\n */\\n address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\\n\\n /**\\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\\n */\\n address public immutable otherMessenger;\\n\\n /**\\n * @custom:legacy\\n * @custom:spacer blockedMessages\\n * @notice Spacer for backwards compatibility.\\n */\\n mapping(bytes32 => bool) private spacer_201_0_32;\\n\\n /**\\n * @custom:legacy\\n * @custom:spacer relayedMessages\\n * @notice Spacer for backwards compatibility.\\n */\\n mapping(bytes32 => bool) private spacer_202_0_32;\\n\\n /**\\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\\n * be present in this mapping if it has successfully been relayed on this chain, and\\n * can therefore not be relayed again.\\n */\\n mapping(bytes32 => bool) public successfulMessages;\\n\\n /**\\n * @notice Address of the sender of the currently executing message on the other chain. If the\\n * value of this variable is the default value (0x00000000...dead) then no message is\\n * currently being executed. Use the xDomainMessageSender getter which will throw an\\n * error if this is the case.\\n */\\n address internal xDomainMsgSender;\\n\\n /**\\n * @notice Nonce for the next message to be sent, without the message version applied. Use the\\n * messageNonce getter which will insert the message version into the nonce to give you\\n * the actual nonce to be used for the message.\\n */\\n uint240 internal msgNonce;\\n\\n /**\\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\\n * be present in this mapping if it failed to be relayed on this chain at least once.\\n * If a message is successfully relayed on the first attempt, then it will only be\\n * present within the successfulMessages mapping.\\n */\\n mapping(bytes32 => bool) public receivedMessages;\\n\\n /**\\n * @notice Reserve extra slots in the storage layout for future upgrades.\\n * A gap size of 41 was chosen here, so that the first slot used in a child contract\\n * would be a multiple of 50.\\n */\\n uint256[42] private __gap;\\n\\n /**\\n * @notice Emitted whenever a message is sent to the other chain.\\n *\\n * @param target Address of the recipient of the message.\\n * @param sender Address of the sender of the message.\\n * @param message Message to trigger the recipient address with.\\n * @param messageNonce Unique nonce attached to the message.\\n * @param gasLimit Minimum gas limit that the message can be executed with.\\n */\\n event SentMessage(\\n address indexed target,\\n address sender,\\n bytes message,\\n uint256 messageNonce,\\n uint256 gasLimit\\n );\\n\\n /**\\n * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\\n * SentMessage event without breaking the ABI of this contract, this is good enough.\\n *\\n * @param sender Address of the sender of the message.\\n * @param value ETH value sent along with the message to the recipient.\\n */\\n event SentMessageExtension1(address indexed sender, uint256 value);\\n\\n /**\\n * @notice Emitted whenever a message is successfully relayed on this chain.\\n *\\n * @param msgHash Hash of the message that was relayed.\\n */\\n event RelayedMessage(bytes32 indexed msgHash);\\n\\n /**\\n * @notice Emitted whenever a message fails to be relayed on this chain.\\n *\\n * @param msgHash Hash of the message that failed to be relayed.\\n */\\n event FailedRelayedMessage(bytes32 indexed msgHash);\\n\\n /**\\n * @param _otherMessenger Address of the messenger on the paired chain.\\n */\\n constructor(address _otherMessenger) {\\n otherMessenger = _otherMessenger;\\n }\\n\\n /**\\n * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\\n * security mechanism just in case. Owner should be the same as the upgrade wallet to\\n * maintain the security model of the system as a whole.\\n */\\n function pause() external onlyOwner {\\n _pause();\\n }\\n\\n /**\\n * @notice Allows the owner of this contract to resume message relaying once paused.\\n */\\n function unpause() external onlyOwner {\\n _unpause();\\n }\\n\\n /**\\n * @notice Sends a message to some target address on the other chain. Note that if the call\\n * always reverts, then the message will be unrelayable, and any ETH sent will be\\n * permanently locked. The same will occur if the target on the other chain is\\n * considered unsafe (see the _isUnsafeTarget() function).\\n *\\n * @param _target Target contract or wallet address.\\n * @param _message Message to trigger the target address with.\\n * @param _minGasLimit Minimum gas limit that the message can be executed with.\\n */\\n function sendMessage(\\n address _target,\\n bytes calldata _message,\\n uint32 _minGasLimit\\n ) external payable {\\n // Triggers a message to the other messenger. Note that the amount of gas provided to the\\n // message is the amount of gas requested by the user PLUS the base gas value. We want to\\n // guarantee the property that the call to the target contract will always have at least\\n // the minimum gas limit specified by the user.\\n _sendMessage(\\n otherMessenger,\\n baseGas(_message, _minGasLimit),\\n msg.value,\\n abi.encodeWithSelector(\\n this.relayMessage.selector,\\n messageNonce(),\\n msg.sender,\\n _target,\\n msg.value,\\n _minGasLimit,\\n _message\\n )\\n );\\n\\n emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\\n emit SentMessageExtension1(msg.sender, msg.value);\\n\\n unchecked {\\n ++msgNonce;\\n }\\n }\\n\\n /**\\n * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\\n * be executed via cross-chain call from the other messenger OR if the message was\\n * already received once and is currently being replayed.\\n *\\n * @param _nonce Nonce of the message being relayed.\\n * @param _sender Address of the user who sent the message.\\n * @param _target Address that the message is targeted at.\\n * @param _value ETH value to send with the message.\\n * @param _minGasLimit Minimum amount of gas that the message can be executed with.\\n * @param _message Message to send to the target.\\n */\\n function relayMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _minGasLimit,\\n bytes calldata _message\\n ) external payable nonReentrant whenNotPaused {\\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\\n\\n // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\\n // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\\n // to the value or minGasLimit fields, which can create unexpected issues for end-users.\\n require(\\n version == 1,\\n \\\"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\\\"\\n );\\n\\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _minGasLimit,\\n _message\\n );\\n\\n if (_isOtherMessenger()) {\\n // This property should always hold when the message is first submitted (as opposed to\\n // being replayed).\\n assert(msg.value == _value);\\n } else {\\n require(\\n msg.value == 0,\\n \\\"CrossDomainMessenger: value must be zero unless message is from a system address\\\"\\n );\\n\\n require(\\n receivedMessages[versionedHash],\\n \\\"CrossDomainMessenger: message cannot be replayed\\\"\\n );\\n }\\n\\n require(\\n _isUnsafeTarget(_target) == false,\\n \\\"CrossDomainMessenger: cannot send message to blocked system address\\\"\\n );\\n\\n require(\\n successfulMessages[versionedHash] == false,\\n \\\"CrossDomainMessenger: message has already been relayed\\\"\\n );\\n\\n require(\\n gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\\n \\\"CrossDomainMessenger: insufficient gas to relay message\\\"\\n );\\n\\n xDomainMsgSender = _sender;\\n bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\\n\\n if (success == true) {\\n successfulMessages[versionedHash] = true;\\n emit RelayedMessage(versionedHash);\\n } else {\\n receivedMessages[versionedHash] = true;\\n emit FailedRelayedMessage(versionedHash);\\n }\\n }\\n\\n /**\\n * @notice Retrieves the address of the contract or wallet that initiated the currently\\n * executing message on the other chain. Will throw an error if there is no message\\n * currently being executed. Allows the recipient of a call to see who triggered it.\\n *\\n * @return Address of the sender of the currently executing message on the other chain.\\n */\\n function xDomainMessageSender() external view returns (address) {\\n require(\\n xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\\n \\\"CrossDomainMessenger: xDomainMessageSender is not set\\\"\\n );\\n\\n return xDomainMsgSender;\\n }\\n\\n /**\\n * @notice Retrieves the next message nonce. Message version will be added to the upper two\\n * bytes of the message nonce. Message version allows us to treat messages as having\\n * different structures.\\n *\\n * @return Nonce of the next message to be sent, with added message version.\\n */\\n function messageNonce() public view returns (uint256) {\\n return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\\n }\\n\\n /**\\n * @notice Computes the amount of gas required to guarantee that a given message will be\\n * received on the other chain without running out of gas. Guaranteeing that a message\\n * will not run out of gas is important because this ensures that a message can always\\n * be replayed on the other chain if it fails to execute completely.\\n *\\n * @param _message Message to compute the amount of required gas for.\\n * @param _minGasLimit Minimum desired gas limit when message goes to target.\\n *\\n * @return Amount of gas required to guarantee message receipt.\\n */\\n function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\\n return\\n // Dynamic overhead\\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\\n // Calldata overhead\\n (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\\n // Constant overhead\\n MIN_GAS_CONSTANT_OVERHEAD;\\n }\\n\\n /**\\n * @notice Intializer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function __CrossDomainMessenger_init() internal onlyInitializing {\\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\\n __Context_init_unchained();\\n __Ownable_init_unchained();\\n __Pausable_init_unchained();\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n /**\\n * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\\n * contracts because the logic for this depends on the network where the messenger is\\n * being deployed.\\n *\\n * @param _to Recipient of the message on the other chain.\\n * @param _gasLimit Minimum gas limit the message can be executed with.\\n * @param _value Amount of ETH to send with the message.\\n * @param _data Message data.\\n */\\n function _sendMessage(\\n address _to,\\n uint64 _gasLimit,\\n uint256 _value,\\n bytes memory _data\\n ) internal virtual;\\n\\n /**\\n * @notice Checks whether the message is coming from the other messenger. Implemented by child\\n * contracts because the logic for this depends on the network where the messenger is\\n * being deployed.\\n *\\n * @return Whether the message is coming from the other messenger.\\n */\\n function _isOtherMessenger() internal view virtual returns (bool);\\n\\n /**\\n * @notice Checks whether a given call target is a system address that could cause the\\n * messenger to peform an unsafe action. This is NOT a mechanism for blocking user\\n * addresses. This is ONLY used to prevent the execution of messages to specific\\n * system addresses that could cause security issues, e.g., having the\\n * CrossDomainMessenger send messages to itself.\\n *\\n * @param _target Address of the contract to check.\\n *\\n * @return Whether or not the address is an unsafe system address.\\n */\\n function _isUnsafeTarget(address _target) internal view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xead7d44e99f3749f1f45e3f70496c27c2d56e532835c13d02b43ee0d8ff1d593\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.15;\\n\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\n\\n/**\\n * @title Semver\\n * @notice Semver is a simple contract for managing contract versions.\\n */\\ncontract Semver {\\n /**\\n * @notice Contract version number (major).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable PATCH_VERSION;\\n\\n /**\\n * @param _major Version number (major).\\n * @param _minor Version number (minor).\\n * @param _patch Version number (patch).\\n */\\n constructor(\\n uint256 _major,\\n uint256 _minor,\\n uint256 _patch\\n ) {\\n MAJOR_VERSION = _major;\\n MINOR_VERSION = _minor;\\n PATCH_VERSION = _patch;\\n }\\n\\n /**\\n * @notice Returns the full semver contract version.\\n *\\n * @return Semver contract version as a string.\\n */\\n function version() public view returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n Strings.toString(MAJOR_VERSION),\\n \\\".\\\",\\n Strings.toString(MINOR_VERSION),\\n \\\".\\\",\\n Strings.toString(PATCH_VERSION)\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x8215e8fbaace5e06fdf0be26cd8ec224847cf03e89bd78dc8ba3ec2cb429d4fe\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\\n * initialization step. This is essential to configure modules that are added through upgrades and that require\\n * initialization.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized < type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x8cc03c5ac17e8a7396e487cda41fc1f1dfdb91db7d528e6da84bee3b6dd7e167\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/L1/L1ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { ERC721Bridge } from \\\"../universal/op-erc721/ERC721Bridge.sol\\\";\\nimport { IERC721 } from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport { L2ERC721Bridge } from \\\"../L2/L2ERC721Bridge.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title L1ERC721Bridge\\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\\n * acts as an escrow for ERC721 tokens deposited into L2.\\n */\\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\\n /**\\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\\n * by ID was deposited for a given L2 token.\\n */\\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(1, 0, 0)\\n ERC721Bridge(_messenger, _otherBridge)\\n {}\\n\\n /*************************\\n * Cross-chain Functions *\\n *************************/\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyOtherBridge {\\n require(_localToken != address(this), \\\"L1ERC721Bridge: local token cannot be self\\\");\\n\\n // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\\n require(\\n deposits[_localToken][_remoteToken][_tokenId] == true,\\n \\\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\\\"\\n );\\n\\n // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\\n // Bridge.\\n deposits[_localToken][_remoteToken][_tokenId] = false;\\n\\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\\n // withdrawer.\\n IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @inheritdoc ERC721Bridge\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal override {\\n require(_remoteToken != address(0), \\\"ERC721Bridge: remote token cannot be address(0)\\\");\\n\\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\\n bytes memory message = abi.encodeWithSelector(\\n L2ERC721Bridge.finalizeBridgeERC721.selector,\\n _remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Lock token into bridge\\n deposits[_localToken][_remoteToken][_tokenId] = true;\\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\\n\\n // Send calldata into L2\\n messenger.sendMessage(otherBridge, message, _minGasLimit);\\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0x966ae750603761f5636063e4d1441759bd7e140ba933303d31c62220e75c8869\",\"license\":\"MIT\"},\"contracts/L2/L2ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { ERC721Bridge } from \\\"../universal/op-erc721/ERC721Bridge.sol\\\";\\nimport { ERC165Checker } from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\nimport { L1ERC721Bridge } from \\\"../L1/L1ERC721Bridge.sol\\\";\\nimport { IOptimismMintableERC721 } from \\\"../universal/op-erc721/IOptimismMintableERC721.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title L2ERC721Bridge\\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\\n * This contract also acts as a burner for tokens being withdrawn.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n */\\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(1, 0, 0)\\n ERC721Bridge(_messenger, _otherBridge)\\n {}\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyOtherBridge {\\n require(_localToken != address(this), \\\"L2ERC721Bridge: local token cannot be self\\\");\\n\\n // Note that supportsInterface makes a callback to the _localToken address which is user\\n // provided.\\n require(\\n ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\\n \\\"L2ERC721Bridge: local token interface is not compliant\\\"\\n );\\n\\n require(\\n _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\\n \\\"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\\\"\\n );\\n\\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\\n // on L2. Note that safeMint makes a callback to the _to address which is user provided.\\n IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @inheritdoc ERC721Bridge\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal override {\\n require(_remoteToken != address(0), \\\"ERC721Bridge: remote token cannot be address(0)\\\");\\n\\n // Check that the withdrawal is being initiated by the NFT owner\\n require(\\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\\n \\\"Withdrawal is not being initiated by NFT owner\\\"\\n );\\n\\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\\n // slither-disable-next-line reentrancy-events\\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\\n require(\\n remoteToken == _remoteToken,\\n \\\"L2ERC721Bridge: remote token does not match given value\\\"\\n );\\n\\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\\n // usage\\n // slither-disable-next-line reentrancy-events\\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\\n\\n bytes memory message = abi.encodeWithSelector(\\n L1ERC721Bridge.finalizeBridgeERC721.selector,\\n remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Send message to L1 bridge\\n // slither-disable-next-line reentrancy-events\\n messenger.sendMessage(otherBridge, message, _minGasLimit);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0xedcf2403f87c8c72790c053b44ccd762e99f5cdf0f362123288d6893b4c856b5\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport {\\n CrossDomainMessenger\\n} from \\\"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\n/**\\n * @title ERC721Bridge\\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\\n */\\nabstract contract ERC721Bridge {\\n /**\\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeInitiated(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFinalized(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Messenger contract on this domain.\\n */\\n CrossDomainMessenger public immutable messenger;\\n\\n /**\\n * @notice Address of the bridge on the other network.\\n */\\n address public immutable otherBridge;\\n\\n /**\\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\\n */\\n uint256[49] private __gap;\\n\\n /**\\n * @notice Ensures that the caller is a cross-chain message from the other bridge.\\n */\\n modifier onlyOtherBridge() {\\n require(\\n msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\\n \\\"ERC721Bridge: function can only be called from the other bridge\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge) {\\n require(_messenger != address(0), \\\"ERC721Bridge: messenger cannot be address(0)\\\");\\n require(_otherBridge != address(0), \\\"ERC721Bridge: other bridge cannot be address(0)\\\");\\n\\n messenger = CrossDomainMessenger(_messenger);\\n otherBridge = _otherBridge;\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\\n * this function can only be called by EOAs. Smart contract wallets should use the\\n * `bridgeERC721To` function after ensuring that the recipient address on the remote\\n * chain exists. Also note that the current owner of the token on this chain must\\n * approve this contract to operate the NFT before it can be bridged.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\\n * be used to execute any code on the other chain and is only emitted as\\n * extra data for the convenience of off-chain tooling.\\n */\\n function bridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n // Modifier requiring sender to be EOA. This prevents against a user error that would occur\\n // if the sender is a smart contract wallet that has a different address on the remote chain\\n // (or doesn't have an address on the remote chain at all). The user would fail to receive\\n // the NFT if they use this function because it sends the NFT to the same address as the\\n // caller. This check could be bypassed by a malicious contract via initcode, but it takes\\n // care of the user error we want to avoid.\\n require(!Address.isContract(msg.sender), \\\"ERC721Bridge: account is not externally owned\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n msg.sender,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\\n * that the current owner of the token on this chain must approve this contract to\\n * operate the NFT before it can be bridged.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\\n * be used to execute any code on the other chain and is only emitted as\\n * extra data for the convenience of off-chain tooling.\\n */\\n function bridgeERC721To(\\n address _localToken,\\n address _remoteToken,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n require(_to != address(0), \\\"ERC721Bridge: nft recipient cannot be address(0)\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n _to,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Internal function for initiating a token bridge to the other domain.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _from Address of the sender on this domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other domain. Data supplied here will\\n * not be used to execute any code on the other domain and is only emitted\\n * as extra data for the convenience of off-chain tooling.\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal virtual;\\n}\\n\",\"keccak256\":\"0x24898e2e75865a4e35cde2d62518cb4c15a30b7cdae8a1a37624a82ae2a26eb7\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/IOptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {\\n IERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\\\";\\n\\n/**\\n * @title IOptimismMintableERC721\\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\\n */\\ninterface IOptimismMintableERC721 is IERC721Enumerable {\\n /**\\n * @notice Emitted when a token is minted.\\n *\\n * @param account Address of the account the token was minted to.\\n * @param tokenId Token ID of the minted token.\\n */\\n event Mint(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Emitted when a token is burned.\\n *\\n * @param account Address of the account the token was burned from.\\n * @param tokenId Token ID of the burned token.\\n */\\n event Burn(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Chain ID of the chain where the remote token is deployed.\\n */\\n function remoteChainId() external view returns (uint256);\\n\\n /**\\n * @notice Address of the token on the remote domain.\\n */\\n function remoteToken() external view returns (address);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n function bridge() external view returns (address);\\n\\n /**\\n * @notice Mints some token ID for a user, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * @param _to Address of the user to mint the token for.\\n * @param _tokenId Token ID to mint.\\n */\\n function safeMint(address _to, uint256 _tokenId) external;\\n\\n /**\\n * @notice Burns a token ID from a user.\\n *\\n * @param _from Address of the user to burn the token from.\\n * @param _tokenId Token ID to burn.\\n */\\n function burn(address _from, uint256 _tokenId) external;\\n}\\n\",\"keccak256\":\"0xc3703030d0093d65839b02296e3152681fa1c8d717e66ab3f5a7c32ba3fd0a54\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6101206040523480156200001257600080fd5b50604051620014fc380380620014fc833981016040819052620000359162000162565b600160008084846001600160a01b038216620000ad5760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b0381166200011d5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401620000a4565b6001600160a01b039182166080521660a05260c09290925260e05261010052506200019a9050565b80516001600160a01b03811681146200015d57600080fd5b919050565b600080604083850312156200017657600080fd5b620001818362000145565b9150620001916020840162000145565b90509250929050565b60805160a05160c05160e051610100516112fb6200020160003960006102930152600061026a0152600061024101526000818161016c0152818161031f0152610aa6015260008181609c015281816102f5015281816103560152610a7701526112fb6000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80635d93a3fc1161005b5780635d93a3fc146100fd578063761f449314610141578063aa55745214610154578063c89701a21461016757600080fd5b80633687011a146100825780633cb747bf1461009757806354fd4d50146100e8575b600080fd5b610095610090366004610d55565b61018e565b005b6100be7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f061023a565b6040516100df9190610e52565b61013161010b366004610e6c565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b60405190151581526020016100df565b61009561014f366004610ead565b6102dd565b610095610162366004610f45565b61075e565b6100be7f000000000000000000000000000000000000000000000000000000000000000081565b333b15610222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610232868633338888888861081a565b505050505050565b60606102657f0000000000000000000000000000000000000000000000000000000000000000610b91565b61028e7f0000000000000000000000000000000000000000000000000000000000000000610b91565b6102b77f0000000000000000000000000000000000000000000000000000000000000000610b91565b6040516020016102c993929190610fbc565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103fb57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190611032565b73ffffffffffffffffffffffffffffffffffffffff16145b610487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f7468657220627269646765006064820152608401610219565b3073ffffffffffffffffffffffffffffffffffffffff88160361052c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c66000000000000000000000000000000000000000000006064820152608401610219565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146105fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c3120427269646765000000000000006064820152608401610219565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106bb57600080fd5b505af11580156106cf573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8787878760405161074d9493929190611098565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610801576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f742062652061646472657373283029000000000000000000000000000000006064820152608401610219565b610811878733888888888861081a565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff87166108bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4552433732314272696467653a2072656d6f746520746f6b656e2063616e6e6f60448201527f74206265206164647265737328302900000000000000000000000000000000006064820152608401610219565b600063761f449360e01b888a89898988886040516024016108e497969594939291906110d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610a2457600080fd5b505af1158015610a38573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610ad2907f00000000000000000000000000000000000000000000000000000000000000009085908990600401611135565b600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610b7e9493929190611098565b60405180910390a4505050505050505050565b606081600003610bd457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610bfe5780610be8816111a9565b9150610bf79050600a83611210565b9150610bd8565b60008167ffffffffffffffff811115610c1957610c19611224565b6040519080825280601f01601f191660200182016040528015610c43576020820181803683370190505b5090505b8415610cc657610c58600183611253565b9150610c65600a8661126a565b610c7090603061127e565b60f81b818381518110610c8557610c85611296565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610cbf600a86611210565b9450610c47565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cf057600080fd5b50565b803563ffffffff81168114610d0757600080fd5b919050565b60008083601f840112610d1e57600080fd5b50813567ffffffffffffffff811115610d3657600080fd5b602083019150836020828501011115610d4e57600080fd5b9250929050565b60008060008060008060a08789031215610d6e57600080fd5b8635610d7981610cce565b95506020870135610d8981610cce565b945060408701359350610d9e60608801610cf3565b9250608087013567ffffffffffffffff811115610dba57600080fd5b610dc689828a01610d0c565b979a9699509497509295939492505050565b60005b83811015610df3578181015183820152602001610ddb565b83811115610e02576000848401525b50505050565b60008151808452610e20816020860160208601610dd8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610e656020830184610e08565b9392505050565b600080600060608486031215610e8157600080fd5b8335610e8c81610cce565b92506020840135610e9c81610cce565b929592945050506040919091013590565b600080600080600080600060c0888a031215610ec857600080fd5b8735610ed381610cce565b96506020880135610ee381610cce565b95506040880135610ef381610cce565b94506060880135610f0381610cce565b93506080880135925060a088013567ffffffffffffffff811115610f2657600080fd5b610f328a828b01610d0c565b989b979a50959850939692959293505050565b600080600080600080600060c0888a031215610f6057600080fd5b8735610f6b81610cce565b96506020880135610f7b81610cce565b95506040880135610f8b81610cce565b945060608801359350610fa060808901610cf3565b925060a088013567ffffffffffffffff811115610f2657600080fd5b60008451610fce818460208901610dd8565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161100a816001850160208a01610dd8565b60019201918201528351611025816002840160208801610dd8565b0160020195945050505050565b60006020828403121561104457600080fd5b8151610e6581610cce565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006110ce60608301848661104f565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261112860c08301848661104f565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111646060830185610e08565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036111da576111da61117a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261121f5761121f6111e1565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156112655761126561117a565b500390565b600082611279576112796111e1565b500690565b600082198211156112915761129161117a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea2646970667358221220e0cdb7d90e665791c254a8f9e836e4238ad139ec9b459c5b8d78a03279211a1664736f6c634300080f0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80635d93a3fc1161005b5780635d93a3fc146100fd578063761f449314610141578063aa55745214610154578063c89701a21461016757600080fd5b80633687011a146100825780633cb747bf1461009757806354fd4d50146100e8575b600080fd5b610095610090366004610d55565b61018e565b005b6100be7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f061023a565b6040516100df9190610e52565b61013161010b366004610e6c565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b60405190151581526020016100df565b61009561014f366004610ead565b6102dd565b610095610162366004610f45565b61075e565b6100be7f000000000000000000000000000000000000000000000000000000000000000081565b333b15610222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610232868633338888888861081a565b505050505050565b60606102657f0000000000000000000000000000000000000000000000000000000000000000610b91565b61028e7f0000000000000000000000000000000000000000000000000000000000000000610b91565b6102b77f0000000000000000000000000000000000000000000000000000000000000000610b91565b6040516020016102c993929190610fbc565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103fb57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190611032565b73ffffffffffffffffffffffffffffffffffffffff16145b610487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f7468657220627269646765006064820152608401610219565b3073ffffffffffffffffffffffffffffffffffffffff88160361052c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c66000000000000000000000000000000000000000000006064820152608401610219565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146105fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c3120427269646765000000000000006064820152608401610219565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106bb57600080fd5b505af11580156106cf573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8787878760405161074d9493929190611098565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610801576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f742062652061646472657373283029000000000000000000000000000000006064820152608401610219565b610811878733888888888861081a565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff87166108bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4552433732314272696467653a2072656d6f746520746f6b656e2063616e6e6f60448201527f74206265206164647265737328302900000000000000000000000000000000006064820152608401610219565b600063761f449360e01b888a89898988886040516024016108e497969594939291906110d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610a2457600080fd5b505af1158015610a38573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610ad2907f00000000000000000000000000000000000000000000000000000000000000009085908990600401611135565b600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610b7e9493929190611098565b60405180910390a4505050505050505050565b606081600003610bd457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610bfe5780610be8816111a9565b9150610bf79050600a83611210565b9150610bd8565b60008167ffffffffffffffff811115610c1957610c19611224565b6040519080825280601f01601f191660200182016040528015610c43576020820181803683370190505b5090505b8415610cc657610c58600183611253565b9150610c65600a8661126a565b610c7090603061127e565b60f81b818381518110610c8557610c85611296565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610cbf600a86611210565b9450610c47565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cf057600080fd5b50565b803563ffffffff81168114610d0757600080fd5b919050565b60008083601f840112610d1e57600080fd5b50813567ffffffffffffffff811115610d3657600080fd5b602083019150836020828501011115610d4e57600080fd5b9250929050565b60008060008060008060a08789031215610d6e57600080fd5b8635610d7981610cce565b95506020870135610d8981610cce565b945060408701359350610d9e60608801610cf3565b9250608087013567ffffffffffffffff811115610dba57600080fd5b610dc689828a01610d0c565b979a9699509497509295939492505050565b60005b83811015610df3578181015183820152602001610ddb565b83811115610e02576000848401525b50505050565b60008151808452610e20816020860160208601610dd8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610e656020830184610e08565b9392505050565b600080600060608486031215610e8157600080fd5b8335610e8c81610cce565b92506020840135610e9c81610cce565b929592945050506040919091013590565b600080600080600080600060c0888a031215610ec857600080fd5b8735610ed381610cce565b96506020880135610ee381610cce565b95506040880135610ef381610cce565b94506060880135610f0381610cce565b93506080880135925060a088013567ffffffffffffffff811115610f2657600080fd5b610f328a828b01610d0c565b989b979a50959850939692959293505050565b600080600080600080600060c0888a031215610f6057600080fd5b8735610f6b81610cce565b96506020880135610f7b81610cce565b95506040880135610f8b81610cce565b945060608801359350610fa060808901610cf3565b925060a088013567ffffffffffffffff811115610f2657600080fd5b60008451610fce818460208901610dd8565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161100a816001850160208a01610dd8565b60019201918201528351611025816002840160208801610dd8565b0160020195945050505050565b60006020828403121561104457600080fd5b8151610e6581610cce565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006110ce60608301848661104f565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261112860c08301848661104f565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111646060830185610e08565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036111da576111da61117a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261121f5761121f6111e1565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156112655761126561117a565b500390565b600082611279576112796111e1565b500690565b600082198211156112915761129161117a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea2646970667358221220e0cdb7d90e665791c254a8f9e836e4238ad139ec9b459c5b8d78a03279211a1664736f6c634300080f0033", + "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": { + "custom:semver": "1.0.0", + "params": { + "_messenger": "Address of the CrossDomainMessenger on this network.", + "_otherBridge": "Address of the ERC721 bridge on the other 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." + } + }, + "version()": { + "returns": { + "_0": "Semver contract version as a string." + } + } + }, + "title": "L1ERC721Bridge", + "version": 1 + }, + "userdoc": { + "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." + } + }, + "kind": "user", + "methods": { + "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." + }, + "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." + }, + "messenger()": { + "notice": "Messenger contract on this domain." + }, + "otherBridge()": { + "notice": "Address of the bridge on the other network." + }, + "version()": { + "notice": "Returns the full semver contract version." + } + }, + "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.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 8088, + "contract": "contracts/L1/L1ERC721Bridge.sol:L1ERC721Bridge", + "label": "__gap", + "offset": 0, + "slot": "0", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 6775, + "contract": "contracts/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)))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "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" + } + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/goerli/L1ERC721BridgeProxy.json b/packages/contracts-periphery/deployments/goerli/L1ERC721BridgeProxy.json new file mode 100644 index 0000000000000..f233a6c393e07 --- /dev/null +++ b/packages/contracts-periphery/deployments/goerli/L1ERC721BridgeProxy.json @@ -0,0 +1,257 @@ +{ + "address": "0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x2e68ff6e214e003d7fc8bd56962ea3751c85096b16bf1a40896c1262ea0e3753", + "receipt": { + "to": null, + "from": "0x5c679a57e018F5F146838138d3E032Ef4913D551", + "contractAddress": "0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9", + "transactionIndex": 31, + "gasUsed": "532674", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000801000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x3c4e33fc274b073565a640b6f1ee49845ea951b4d73f1645aef83dd70c110ba8", + "transactionHash": "0x2e68ff6e214e003d7fc8bd56962ea3751c85096b16bf1a40896c1262ea0e3753", + "logs": [ + { + "transactionIndex": 31, + "blockNumber": 7682740, + "transactionHash": "0x2e68ff6e214e003d7fc8bd56962ea3751c85096b16bf1a40896c1262ea0e3753", + "address": "0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000005c679a57e018f5f146838138d3e032ef4913d551", + "logIndex": 76, + "blockHash": "0x3c4e33fc274b073565a640b6f1ee49845ea951b4d73f1645aef83dd70c110ba8" + } + ], + "blockNumber": 7682740, + "cumulativeGasUsed": "22398486", + "status": 1, + "byzantium": true + }, + "args": [ + "0x5c679a57e018F5F146838138d3E032Ef4913D551" + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"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\"}}},\"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.\"}}},\"title\":\"Proxy\",\"version\":1},\"userdoc\":{\"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.\"}},\"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.\"},\"implementation()\":{\"notice\":\"Queries the implementation address.\"},\"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.\"}},\"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.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title Proxy\\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\\n * if the caller is address(0), meaning that the call originated from an off-chain\\n * simulation.\\n */\\ncontract Proxy {\\n /**\\n * @notice The storage slot that holds the address of the implementation.\\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n */\\n bytes32 internal constant IMPLEMENTATION_KEY =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @notice The storage slot that holds the address of the owner.\\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n */\\n bytes32 internal constant OWNER_KEY =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @notice An event that is emitted each time the implementation is changed. This event is part\\n * of the EIP-1967 specification.\\n *\\n * @param implementation The address of the implementation contract\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\\n * EIP-1967 specification.\\n *\\n * @param previousAdmin The previous owner of the contract\\n * @param newAdmin The new owner of the contract\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\\n * eth_call to interact with this proxy without needing to use low-level storage\\n * inspection. We assume that nobody is able to trigger calls from address(0) during\\n * normal EVM execution.\\n */\\n modifier proxyCallIfNotAdmin() {\\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\\n _;\\n } else {\\n // This WILL halt the call frame on completion.\\n _doProxyCall();\\n }\\n }\\n\\n /**\\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\\n * EIP-1967 admin storage slot so that accidental storage collision with the\\n * implementation is not possible.\\n *\\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\\n * transparent proxy interface.\\n */\\n constructor(address _admin) {\\n _changeAdmin(_admin);\\n }\\n\\n // slither-disable-next-line locked-ether\\n receive() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n // slither-disable-next-line locked-ether\\n fallback() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n /**\\n * @notice Set the implementation contract address. The code at the given address will execute\\n * when this contract is called.\\n *\\n * @param _implementation Address of the implementation contract.\\n */\\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\\n _setImplementation(_implementation);\\n }\\n\\n /**\\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\\n * atomic execution of initialization-based upgrades.\\n *\\n * @param _implementation Address of the implementation contract.\\n * @param _data Calldata to delegatecall the new implementation with.\\n */\\n function upgradeToAndCall(address _implementation, bytes calldata _data)\\n external\\n payable\\n proxyCallIfNotAdmin\\n returns (bytes memory)\\n {\\n _setImplementation(_implementation);\\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\\n require(success, \\\"Proxy: delegatecall to new implementation contract failed\\\");\\n return returndata;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\\n _changeAdmin(_admin);\\n }\\n\\n /**\\n * @notice Gets the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function admin() external proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() external proxyCallIfNotAdmin returns (address) {\\n return _getImplementation();\\n }\\n\\n /**\\n * @notice Sets the implementation address.\\n *\\n * @param _implementation New implementation address.\\n */\\n function _setImplementation(address _implementation) internal {\\n assembly {\\n sstore(IMPLEMENTATION_KEY, _implementation)\\n }\\n emit Upgraded(_implementation);\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function _changeAdmin(address _admin) internal {\\n address previous = _getAdmin();\\n assembly {\\n sstore(OWNER_KEY, _admin)\\n }\\n emit AdminChanged(previous, _admin);\\n }\\n\\n /**\\n * @notice Performs the proxy call via a delegatecall.\\n */\\n function _doProxyCall() internal {\\n address impl = _getImplementation();\\n require(impl != address(0), \\\"Proxy: implementation not initialized\\\");\\n\\n assembly {\\n // Copy calldata into memory at 0x0....calldatasize.\\n calldatacopy(0x0, 0x0, calldatasize())\\n\\n // Perform the delegatecall, make sure to pass all available gas.\\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\\n\\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\\n // overwrite the calldata that we just copied into memory but that doesn't really\\n // matter because we'll be returning in a second anyway.\\n returndatacopy(0x0, 0x0, returndatasize())\\n\\n // Success == 0 means a revert. We'll revert too and pass the data up.\\n if iszero(success) {\\n revert(0x0, returndatasize())\\n }\\n\\n // Otherwise we'll just return and pass the data up.\\n return(0x0, returndatasize())\\n }\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n address impl;\\n assembly {\\n impl := sload(IMPLEMENTATION_KEY)\\n }\\n return impl;\\n }\\n\\n /**\\n * @notice Queries the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function _getAdmin() internal view returns (address) {\\n address owner;\\n assembly {\\n owner := sload(OWNER_KEY)\\n }\\n return owner;\\n }\\n}\\n\",\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5060405161094138038061094183398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206109218339815191525490565b600080516020610921833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610830806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033", + "devdoc": { + "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" + } + } + }, + "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." + } + } + }, + "title": "Proxy", + "version": 1 + }, + "userdoc": { + "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." + } + }, + "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." + }, + "implementation()": { + "notice": "Queries the implementation address." + }, + "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." + } + }, + "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.", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/goerli/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json b/packages/contracts-periphery/deployments/goerli/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json new file mode 100644 index 0000000000000..91d5f99068af8 --- /dev/null +++ b/packages/contracts-periphery/deployments/goerli/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json @@ -0,0 +1,173 @@ +{ + "language": "Solidity", + "sources": { + "contracts/L1/L1ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L1ERC721Bridge\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as an escrow for ERC721 tokens deposited into L2.\n */\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\n * by ID was deposited for a given L2 token.\n */\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\n * execute any code on L2 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L1ERC721Bridge: local token cannot be self\");\n\n // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\n require(\n deposits[_localToken][_remoteToken][_tokenId] == true,\n \"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\"\n );\n\n // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\n // Bridge.\n deposits[_localToken][_remoteToken][_tokenId] = false;\n\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\n // withdrawer.\n IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\n bytes memory message = abi.encodeWithSelector(\n L2ERC721Bridge.finalizeBridgeERC721.selector,\n _remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Lock token into bridge\n deposits[_localToken][_remoteToken][_tokenId] = true;\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\n\n // Send calldata into L2\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "contracts/universal/op-erc721/ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n CrossDomainMessenger\n} from \"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title ERC721Bridge\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\n */\nabstract contract ERC721Bridge {\n /**\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable messenger;\n\n /**\n * @notice Address of the bridge on the other network.\n */\n address public immutable otherBridge;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[49] private __gap;\n\n /**\n * @notice Ensures that the caller is a cross-chain message from the other bridge.\n */\n modifier onlyOtherBridge() {\n require(\n msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\n \"ERC721Bridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge) {\n require(_messenger != address(0), \"ERC721Bridge: messenger cannot be address(0)\");\n require(_otherBridge != address(0), \"ERC721Bridge: other bridge cannot be address(0)\");\n\n messenger = CrossDomainMessenger(_messenger);\n otherBridge = _otherBridge;\n }\n\n /**\n * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\n * this function can only be called by EOAs. Smart contract wallets should use the\n * `bridgeERC721To` function after ensuring that the recipient address on the remote\n * chain exists. Also note that the current owner of the token on this chain must\n * approve this contract to operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721(\n address _localToken,\n address _remoteToken,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n // Modifier requiring sender to be EOA. This prevents against a user error that would occur\n // if the sender is a smart contract wallet that has a different address on the remote chain\n // (or doesn't have an address on the remote chain at all). The user would fail to receive\n // the NFT if they use this function because it sends the NFT to the same address as the\n // caller. This check could be bypassed by a malicious contract via initcode, but it takes\n // care of the user error we want to avoid.\n require(!Address.isContract(msg.sender), \"ERC721Bridge: account is not externally owned\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\n * that the current owner of the token on this chain must approve this contract to\n * operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n require(_to != address(0), \"ERC721Bridge: nft recipient cannot be address(0)\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Internal function for initiating a token bridge to the other domain.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _from Address of the sender on this domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other domain. Data supplied here will\n * not be used to execute any code on the other domain and is only emitted\n * as extra data for the convenience of off-chain tooling.\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal virtual;\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "contracts/L2/L2ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/op-erc721/IOptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L2ERC721Bridge\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\n * This contract also acts as a burner for tokens being withdrawn.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n */\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\n * execute any code on L1 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L2ERC721Bridge: local token cannot be self\");\n\n // Note that supportsInterface makes a callback to the _localToken address which is user\n // provided.\n require(\n ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\n \"L2ERC721Bridge: local token interface is not compliant\"\n );\n\n require(\n _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\n \"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\"\n );\n\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\n // on L2. Note that safeMint makes a callback to the _to address which is user provided.\n IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Check that the withdrawal is being initiated by the NFT owner\n require(\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\n \"Withdrawal is not being initiated by NFT owner\"\n );\n\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\n // slither-disable-next-line reentrancy-events\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\n require(\n remoteToken == _remoteToken,\n \"L2ERC721Bridge: remote token does not match given value\"\n );\n\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\n // usage\n // slither-disable-next-line reentrancy-events\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\n\n bytes memory message = abi.encodeWithSelector(\n L1ERC721Bridge.finalizeBridgeERC721.selector,\n remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Send message to L1 bridge\n // slither-disable-next-line reentrancy-events\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\n\n/**\n * @title Semver\n * @notice Semver is a simple contract for managing contract versions.\n */\ncontract Semver {\n /**\n * @notice Contract version number (major).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable PATCH_VERSION;\n\n /**\n * @param _major Version number (major).\n * @param _minor Version number (minor).\n * @param _patch Version number (patch).\n */\n constructor(\n uint256 _major,\n uint256 _minor,\n uint256 _patch\n ) {\n MAJOR_VERSION = _major;\n MINOR_VERSION = _minor;\n PATCH_VERSION = _patch;\n }\n\n /**\n * @notice Returns the full semver contract version.\n *\n * @return Semver contract version as a string.\n */\n function version() public view returns (string memory) {\n return\n string(\n abi.encodePacked(\n Strings.toString(MAJOR_VERSION),\n \".\",\n Strings.toString(MINOR_VERSION),\n \".\",\n Strings.toString(PATCH_VERSION)\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n PausableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {\n ReentrancyGuardUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * libAddressManager variable used to exist. Must be the first contract in the inheritance\n * tree of the CrossDomainMessenger\n */\ncontract CrossDomainMessengerLegacySpacer {\n /**\n * @custom:legacy\n * @custom:spacer libAddressManager\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n}\n\n/**\n * @custom:upgradeable\n * @title CrossDomainMessenger\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\n * cross-chain messenger contracts. It's designed to be a universal interface that only\n * needs to be extended slightly to provide low-level message passing functionality on each\n * chain it's deployed on. Currently only designed for message passing between two paired\n * chains and does not support one-to-many interactions.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer,\n OwnableUpgradeable,\n PausableUpgradeable,\n ReentrancyGuardUpgradeable\n{\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Constant overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\n\n /**\n * @notice Numerator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\n\n /**\n * @notice Denominator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\n\n /**\n * @notice Extra gas added to base gas for each byte of calldata in a message.\n */\n uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Minimum amount of gas required to relay a message.\n */\n uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\n\n /**\n * @notice Amount of gas held in reserve to guarantee that relay execution completes.\n */\n uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\n\n /**\n * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\n * because performing an SSTORE on a non-zero value is significantly cheaper than on a\n * zero value.\n */\n address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable otherMessenger;\n\n /**\n * @custom:legacy\n * @custom:spacer blockedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_201_0_32;\n\n /**\n * @custom:legacy\n * @custom:spacer relayedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_202_0_32;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it has successfully been relayed on this chain, and\n * can therefore not be relayed again.\n */\n mapping(bytes32 => bool) public successfulMessages;\n\n /**\n * @notice Address of the sender of the currently executing message on the other chain. If the\n * value of this variable is the default value (0x00000000...dead) then no message is\n * currently being executed. Use the xDomainMessageSender getter which will throw an\n * error if this is the case.\n */\n address internal xDomainMsgSender;\n\n /**\n * @notice Nonce for the next message to be sent, without the message version applied. Use the\n * messageNonce getter which will insert the message version into the nonce to give you\n * the actual nonce to be used for the message.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it failed to be relayed on this chain at least once.\n * If a message is successfully relayed on the first attempt, then it will only be\n * present within the successfulMessages mapping.\n */\n mapping(bytes32 => bool) public receivedMessages;\n\n /**\n * @notice Reserve extra slots in the storage layout for future upgrades.\n * A gap size of 41 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[42] private __gap;\n\n /**\n * @notice Emitted whenever a message is sent to the other chain.\n *\n * @param target Address of the recipient of the message.\n * @param sender Address of the sender of the message.\n * @param message Message to trigger the recipient address with.\n * @param messageNonce Unique nonce attached to the message.\n * @param gasLimit Minimum gas limit that the message can be executed with.\n */\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n /**\n * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\n * SentMessage event without breaking the ABI of this contract, this is good enough.\n *\n * @param sender Address of the sender of the message.\n * @param value ETH value sent along with the message to the recipient.\n */\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n /**\n * @notice Emitted whenever a message is successfully relayed on this chain.\n *\n * @param msgHash Hash of the message that was relayed.\n */\n event RelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @notice Emitted whenever a message fails to be relayed on this chain.\n *\n * @param msgHash Hash of the message that failed to be relayed.\n */\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @param _otherMessenger Address of the messenger on the paired chain.\n */\n constructor(address _otherMessenger) {\n otherMessenger = _otherMessenger;\n }\n\n /**\n * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\n * security mechanism just in case. Owner should be the same as the upgrade wallet to\n * maintain the security model of the system as a whole.\n */\n function pause() external onlyOwner {\n _pause();\n }\n\n /**\n * @notice Allows the owner of this contract to resume message relaying once paused.\n */\n function unpause() external onlyOwner {\n _unpause();\n }\n\n /**\n * @notice Sends a message to some target address on the other chain. Note that if the call\n * always reverts, then the message will be unrelayable, and any ETH sent will be\n * permanently locked. The same will occur if the target on the other chain is\n * considered unsafe (see the _isUnsafeTarget() function).\n *\n * @param _target Target contract or wallet address.\n * @param _message Message to trigger the target address with.\n * @param _minGasLimit Minimum gas limit that the message can be executed with.\n */\n function sendMessage(\n address _target,\n bytes calldata _message,\n uint32 _minGasLimit\n ) external payable {\n // Triggers a message to the other messenger. Note that the amount of gas provided to the\n // message is the amount of gas requested by the user PLUS the base gas value. We want to\n // guarantee the property that the call to the target contract will always have at least\n // the minimum gas limit specified by the user.\n _sendMessage(\n otherMessenger,\n baseGas(_message, _minGasLimit),\n msg.value,\n abi.encodeWithSelector(\n this.relayMessage.selector,\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _minGasLimit,\n _message\n )\n );\n\n emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\n emit SentMessageExtension1(msg.sender, msg.value);\n\n unchecked {\n ++msgNonce;\n }\n }\n\n /**\n * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\n * be executed via cross-chain call from the other messenger OR if the message was\n * already received once and is currently being replayed.\n *\n * @param _nonce Nonce of the message being relayed.\n * @param _sender Address of the user who sent the message.\n * @param _target Address that the message is targeted at.\n * @param _value ETH value to send with the message.\n * @param _minGasLimit Minimum amount of gas that the message can be executed with.\n * @param _message Message to send to the target.\n */\n function relayMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _minGasLimit,\n bytes calldata _message\n ) external payable nonReentrant whenNotPaused {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n\n // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\n // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\n // to the value or minGasLimit fields, which can create unexpected issues for end-users.\n require(\n version == 1,\n \"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\"\n );\n\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n if (_isOtherMessenger()) {\n // This property should always hold when the message is first submitted (as opposed to\n // being replayed).\n assert(msg.value == _value);\n } else {\n require(\n msg.value == 0,\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n\n require(\n receivedMessages[versionedHash],\n \"CrossDomainMessenger: message cannot be replayed\"\n );\n }\n\n require(\n _isUnsafeTarget(_target) == false,\n \"CrossDomainMessenger: cannot send message to blocked system address\"\n );\n\n require(\n successfulMessages[versionedHash] == false,\n \"CrossDomainMessenger: message has already been relayed\"\n );\n\n require(\n gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\n \"CrossDomainMessenger: insufficient gas to relay message\"\n );\n\n xDomainMsgSender = _sender;\n bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n\n if (success == true) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n receivedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n }\n }\n\n /**\n * @notice Retrieves the address of the contract or wallet that initiated the currently\n * executing message on the other chain. Will throw an error if there is no message\n * currently being executed. Allows the recipient of a call to see who triggered it.\n *\n * @return Address of the sender of the currently executing message on the other chain.\n */\n function xDomainMessageSender() external view returns (address) {\n require(\n xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\n \"CrossDomainMessenger: xDomainMessageSender is not set\"\n );\n\n return xDomainMsgSender;\n }\n\n /**\n * @notice Retrieves the next message nonce. Message version will be added to the upper two\n * bytes of the message nonce. Message version allows us to treat messages as having\n * different structures.\n *\n * @return Nonce of the next message to be sent, with added message version.\n */\n function messageNonce() public view returns (uint256) {\n return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\n }\n\n /**\n * @notice Computes the amount of gas required to guarantee that a given message will be\n * received on the other chain without running out of gas. Guaranteeing that a message\n * will not run out of gas is important because this ensures that a message can always\n * be replayed on the other chain if it fails to execute completely.\n *\n * @param _message Message to compute the amount of required gas for.\n * @param _minGasLimit Minimum desired gas limit when message goes to target.\n *\n * @return Amount of gas required to guarantee message receipt.\n */\n function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\n return\n // Dynamic overhead\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\n // Constant overhead\n MIN_GAS_CONSTANT_OVERHEAD;\n }\n\n /**\n * @notice Intializer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __CrossDomainMessenger_init() internal onlyInitializing {\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n __ReentrancyGuard_init_unchained();\n }\n\n /**\n * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @param _to Recipient of the message on the other chain.\n * @param _gasLimit Minimum gas limit the message can be executed with.\n * @param _value Amount of ETH to send with the message.\n * @param _data Message data.\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal virtual;\n\n /**\n * @notice Checks whether the message is coming from the other messenger. Implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @return Whether the message is coming from the other messenger.\n */\n function _isOtherMessenger() internal view virtual returns (bool);\n\n /**\n * @notice Checks whether a given call target is a system address that could cause the\n * messenger to peform an unsafe action. This is NOT a mechanism for blocking user\n * addresses. This is ONLY used to prevent the execution of messages to specific\n * system addresses that could cause security issues, e.g., having the\n * CrossDomainMessenger send messages to itself.\n *\n * @param _target Address of the contract to check.\n *\n * @return Whether or not the address is an unsafe system address.\n */\n function _isUnsafeTarget(address _target) internal view virtual returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title SafeCall\n * @notice Perform low level safe calls\n */\nlibrary SafeCall {\n /**\n * @notice Perform a low level call without copying any returndata\n *\n * @param _target Address to call\n * @param _gas Amount of gas to pass to the call\n * @param _value Amount of value to pass to the call\n * @param _calldata Calldata to pass to the call\n */\n function call(\n address _target,\n uint256 _gas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n assembly {\n _success := call(\n _gas, // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Encoding } from \"./Encoding.sol\";\n\n/**\n * @title Hashing\n * @notice Hashing handles Optimism's various different hashing schemes.\n */\nlibrary Hashing {\n /**\n * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\n * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\n * system.\n *\n * @param _tx User deposit transaction to hash.\n *\n * @return Hash of the RLP encoded L2 deposit transaction.\n */\n function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return keccak256(Encoding.encodeDepositTransaction(_tx));\n }\n\n /**\n * @notice Computes the deposit transaction's \"source hash\", a value that guarantees the hash\n * of the L2 transaction that corresponds to a deposit is unique and is\n * deterministically generated from L1 transaction data.\n *\n * @param _l1BlockHash Hash of the L1 block where the deposit was included.\n * @param _logIndex The index of the log that created the deposit transaction.\n *\n * @return Hash of the deposit transaction's \"source hash\".\n */\n function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\n internal\n pure\n returns (bytes32)\n {\n bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\n return keccak256(abi.encode(bytes32(0), depositId));\n }\n\n /**\n * @notice Hashes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n if (version == 0) {\n return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Hashing: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes32) {\n return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\n }\n\n /**\n * @notice Hashes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n return\n keccak256(\n Encoding.encodeCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n )\n );\n }\n\n /**\n * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\n *\n * @param _tx Withdrawal transaction to hash.\n *\n * @return Hashed withdrawal transaction.\n */\n function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\n );\n }\n\n /**\n * @notice Hashes the various elements of an output root proof into an output root hash which\n * can be used to check if the proof is valid.\n *\n * @param _outputRootProof Output root proof which should hash to an output root.\n *\n * @return Hashed output root proof.\n */\n function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(\n _outputRootProof.version,\n _outputRootProof.stateRoot,\n _outputRootProof.messagePasserStorageRoot,\n _outputRootProof.latestBlockhash\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Hashing } from \"./Hashing.sol\";\nimport { RLPWriter } from \"./rlp/RLPWriter.sol\";\n\n/**\n * @title Encoding\n * @notice Encoding handles Optimism's various different encoding schemes.\n */\nlibrary Encoding {\n /**\n * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\n * to the L2 system. Useful for searching for a deposit in the L2 system. The\n * transaction is prefixed with 0x7e to identify its EIP-2718 type.\n *\n * @param _tx User deposit transaction to encode.\n *\n * @return RLP encoded L2 deposit transaction.\n */\n function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes memory)\n {\n bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\n bytes[] memory raw = new bytes[](8);\n raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\n raw[1] = RLPWriter.writeAddress(_tx.from);\n raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\"\") : RLPWriter.writeAddress(_tx.to);\n raw[3] = RLPWriter.writeUint(_tx.mint);\n raw[4] = RLPWriter.writeUint(_tx.value);\n raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\n raw[6] = RLPWriter.writeBool(false);\n raw[7] = RLPWriter.writeBytes(_tx.data);\n return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\n }\n\n /**\n * @notice Encodes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n (, uint16 version) = decodeVersionedNonce(_nonce);\n if (version == 0) {\n return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Encoding: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _data,\n _nonce\n );\n }\n\n /**\n * @notice Encodes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(uint256,address,address,uint256,uint256,bytes)\",\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n }\n\n /**\n * @notice Adds a version number into the first two bytes of a message nonce.\n *\n * @param _nonce Message nonce to encode into.\n * @param _version Version number to encode into the message nonce.\n *\n * @return Message nonce with version encoded into the first two bytes.\n */\n function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\n uint256 nonce;\n assembly {\n nonce := or(shl(240, _version), _nonce)\n }\n return nonce;\n }\n\n /**\n * @notice Pulls the version out of a version-encoded nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n *\n * @return Nonce without encoded version.\n * @return Version of the message.\n */\n function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\n uint240 nonce;\n uint16 version;\n assembly {\n nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n version := shr(240, _nonce)\n }\n return (nonce, version);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Types\n * @notice Contains various types used throughout the Optimism contract system.\n */\nlibrary Types {\n /**\n * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\n * timestamp that the output root is posted. This timestamp is used to verify that the\n * finalization period has passed since the output root was submitted.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint256 timestamp;\n }\n\n /**\n * @notice Struct representing the elements that are hashed together to generate an output root\n * which itself represents a snapshot of the L2 state.\n */\n struct OutputRootProof {\n bytes32 version;\n bytes32 stateRoot;\n bytes32 messagePasserStorageRoot;\n bytes32 latestBlockhash;\n }\n\n /**\n * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\n * user (as opposed to a system deposit transaction generated by the system).\n */\n struct UserDepositTransaction {\n address from;\n address to;\n bool isCreation;\n uint256 value;\n uint256 mint;\n uint64 gasLimit;\n bytes data;\n bytes32 l1BlockHash;\n uint256 logIndex;\n }\n\n /**\n * @notice Struct representing a withdrawal transaction.\n */\n struct WithdrawalTransaction {\n uint256 nonce;\n address sender;\n address target;\n uint256 value;\n uint256 gasLimit;\n bytes data;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\n * @title RLPWriter\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\n * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\n * modifications to improve legibility.\n */\nlibrary RLPWriter {\n /**\n * @notice RLP encodes a byte string.\n *\n * @param _in The byte string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_in.length == 1 && uint8(_in[0]) < 128) {\n encoded = _in;\n } else {\n encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\n }\n\n return encoded;\n }\n\n /**\n * @notice RLP encodes a list of RLP encoded byte byte strings.\n *\n * @param _in The list of RLP encoded byte strings.\n *\n * @return The RLP encoded list of items in bytes.\n */\n function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\n bytes memory list = _flatten(_in);\n return abi.encodePacked(_writeLength(list.length, 192), list);\n }\n\n /**\n * @notice RLP encodes a string.\n *\n * @param _in The string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeString(string memory _in) internal pure returns (bytes memory) {\n return writeBytes(bytes(_in));\n }\n\n /**\n * @notice RLP encodes an address.\n *\n * @param _in The address to encode.\n *\n * @return The RLP encoded address in bytes.\n */\n function writeAddress(address _in) internal pure returns (bytes memory) {\n return writeBytes(abi.encodePacked(_in));\n }\n\n /**\n * @notice RLP encodes a uint.\n *\n * @param _in The uint256 to encode.\n *\n * @return The RLP encoded uint256 in bytes.\n */\n function writeUint(uint256 _in) internal pure returns (bytes memory) {\n return writeBytes(_toBinary(_in));\n }\n\n /**\n * @notice RLP encodes a bool.\n *\n * @param _in The bool to encode.\n *\n * @return The RLP encoded bool in bytes.\n */\n function writeBool(bool _in) internal pure returns (bytes memory) {\n bytes memory encoded = new bytes(1);\n encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n return encoded;\n }\n\n /**\n * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\n *\n * @param _len The length of the string or the payload.\n * @param _offset 128 if item is string, 192 if item is list.\n *\n * @return RLP encoded bytes.\n */\n function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_len < 56) {\n encoded = new bytes(1);\n encoded[0] = bytes1(uint8(_len) + uint8(_offset));\n } else {\n uint256 lenLen;\n uint256 i = 1;\n while (_len / i != 0) {\n lenLen++;\n i *= 256;\n }\n\n encoded = new bytes(lenLen + 1);\n encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\n for (i = 1; i <= lenLen; i++) {\n encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\n }\n }\n\n return encoded;\n }\n\n /**\n * @notice Encode integer in big endian binary form with no leading zeroes.\n *\n * @param _x The integer to encode.\n *\n * @return RLP encoded bytes.\n */\n function _toBinary(uint256 _x) private pure returns (bytes memory) {\n bytes memory b = abi.encodePacked(_x);\n\n uint256 i = 0;\n for (; i < 32; i++) {\n if (b[i] != 0) {\n break;\n }\n }\n\n bytes memory res = new bytes(32 - i);\n for (uint256 j = 0; j < res.length; j++) {\n res[j] = b[i++];\n }\n\n return res;\n }\n\n /**\n * @custom:attribution https://github.com/Arachnid/solidity-stringutils\n * @notice Copies a piece of memory to another location.\n *\n * @param _dest Destination location.\n * @param _src Source location.\n * @param _len Length of memory to copy.\n */\n function _memcpy(\n uint256 _dest,\n uint256 _src,\n uint256 _len\n ) private pure {\n uint256 dest = _dest;\n uint256 src = _src;\n uint256 len = _len;\n\n for (; len >= 32; len -= 32) {\n assembly {\n mstore(dest, mload(src))\n }\n dest += 32;\n src += 32;\n }\n\n uint256 mask;\n unchecked {\n mask = 256**(32 - len) - 1;\n }\n assembly {\n let srcpart := and(mload(src), not(mask))\n let destpart := and(mload(dest), mask)\n mstore(dest, or(destpart, srcpart))\n }\n }\n\n /**\n * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\n * @notice Flattens a list of byte strings into one byte string.\n *\n * @param _list List of byte strings to flatten.\n *\n * @return The flattened byte string.\n */\n function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\n if (_list.length == 0) {\n return new bytes(0);\n }\n\n uint256 len;\n uint256 i = 0;\n for (; i < _list.length; i++) {\n len += _list[i].length;\n }\n\n bytes memory flattened = new bytes(len);\n uint256 flattenedPtr;\n assembly {\n flattenedPtr := add(flattened, 0x20)\n }\n\n for (i = 0; i < _list.length; i++) {\n bytes memory item = _list[i];\n\n uint256 listPtr;\n assembly {\n listPtr := add(item, 0x20)\n }\n\n _memcpy(flattenedPtr, listPtr, item.length);\n flattenedPtr += _list[i].length;\n }\n\n return flattened;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" + }, + "contracts/universal/op-erc721/IOptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n IERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\";\n\n/**\n * @title IOptimismMintableERC721\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\n */\ninterface IOptimismMintableERC721 is IERC721Enumerable {\n /**\n * @notice Emitted when a token is minted.\n *\n * @param account Address of the account the token was minted to.\n * @param tokenId Token ID of the minted token.\n */\n event Mint(address indexed account, uint256 tokenId);\n\n /**\n * @notice Emitted when a token is burned.\n *\n * @param account Address of the account the token was burned from.\n * @param tokenId Token ID of the burned token.\n */\n event Burn(address indexed account, uint256 tokenId);\n\n /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function remoteChainId() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function remoteToken() external view returns (address);\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n function bridge() external view returns (address);\n\n /**\n * @notice Mints some token ID for a user, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * @param _to Address of the user to mint the token for.\n * @param _tokenId Token ID to mint.\n */\n function safeMint(address _to, uint256 _tokenId) external;\n\n /**\n * @notice Burns a token ID from a user.\n *\n * @param _from Address of the user to burn the token from.\n * @param _tokenId Token ID to burn.\n */\n function burn(address _from, uint256 _tokenId) external;\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n /**\n * @dev Returns the total amount of tokens stored by the contract.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n /**\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n * Use along with {totalSupply} to enumerate all tokens.\n */\n function tokenByIndex(uint256 index) external view returns (uint256);\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismMintableERC721 } from \"./OptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC721Factory\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\n */\ncontract OptimismMintableERC721Factory is Semver {\n /**\n * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\n *\n * @param localToken Address of the token on the this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param deployer Address of the initiator of the deployment\n */\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n address public immutable bridge;\n\n /**\n * @notice Chain ID for the remote network.\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 0, 0) {\n require(\n _bridge != address(0),\n \"OptimismMintableERC721Factory: bridge cannot be address(0)\"\n );\n require(\n _remoteChainId != 0,\n \"OptimismMintableERC721Factory: remote chain id cannot be zero\"\n );\n\n bridge = _bridge;\n remoteChainId = _remoteChainId;\n }\n\n /**\n * @notice Creates an instance of the standard ERC721.\n *\n * @param _remoteToken Address of the corresponding token on the other domain.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n function createOptimismMintableERC721(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721Factory: L1 token address cannot be address(0)\"\n );\n\n address localToken = address(\n new OptimismMintableERC721(bridge, remoteChainId, _remoteToken, _name, _symbol)\n );\n\n isOptimismMintableERC721[localToken] = true;\n emit OptimismMintableERC721Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n ERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { IOptimismMintableERC721 } from \"./IOptimismMintableERC721.sol\";\n\n/**\n * @title OptimismMintableERC721\n * @notice This contract is the remote representation for some token that lives on another network,\n * typically an Optimism representation of an Ethereum-based token. Standard reference\n * implementation that can be extended or modified according to your needs.\n */\ncontract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable remoteToken;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable bridge;\n\n /**\n * @notice Base token URI for this token.\n */\n string public baseTokenURI;\n\n /**\n * @param _bridge Address of the bridge on this network.\n * @param _remoteChainId Chain ID where the remote token is deployed.\n * @param _remoteToken Address of the corresponding token on the other network.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n constructor(\n address _bridge,\n uint256 _remoteChainId,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC721(_name, _symbol) {\n require(_bridge != address(0), \"OptimismMintableERC721: bridge cannot be address(0)\");\n require(_remoteChainId != 0, \"OptimismMintableERC721: remote chain id cannot be zero\");\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721: remote token cannot be address(0)\"\n );\n\n remoteChainId = _remoteChainId;\n remoteToken = _remoteToken;\n bridge = _bridge;\n\n // Creates a base URI in the format specified by EIP-681:\n // https://eips.ethereum.org/EIPS/eip-681\n baseTokenURI = string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(_remoteToken), 20),\n \"@\",\n Strings.toString(_remoteChainId),\n \"/tokenURI?uint256=\"\n )\n );\n }\n\n /**\n * @notice Modifier that prevents callers other than the bridge from calling the function.\n */\n modifier onlyBridge() {\n require(msg.sender == bridge, \"OptimismMintableERC721: only bridge can call this function\");\n _;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {\n _safeMint(_to, _tokenId);\n\n emit Mint(_to, _tokenId);\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function burn(address _from, uint256 _tokenId) external virtual onlyBridge {\n _burn(_tokenId);\n\n emit Burn(_from, _tokenId);\n }\n\n /**\n * @notice Checks if a given interface ID is supported by this contract.\n *\n * @param _interfaceId The interface ID to check.\n *\n * @return True if the interface ID is supported, false otherwise.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n override(ERC721Enumerable, IERC165)\n returns (bool)\n {\n bytes4 iface1 = type(IERC165).interfaceId;\n bytes4 iface2 = type(IOptimismMintableERC721).interfaceId;\n return\n _interfaceId == iface1 ||\n _interfaceId == iface2 ||\n super.supportsInterface(_interfaceId);\n }\n\n /**\n * @notice Returns the base token URI.\n *\n * @return Base token URI.\n */\n function _baseURI() internal view virtual override returns (string memory) {\n return baseTokenURI;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721.sol\";\nimport \"./IERC721Enumerable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\n // Mapping from owner to list of owned token IDs\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n // Mapping from token ID to index of the owner tokens list\n mapping(uint256 => uint256) private _ownedTokensIndex;\n\n // Array with all token ids, used for enumeration\n uint256[] private _allTokens;\n\n // Mapping from token id to position in the allTokens array\n mapping(uint256 => uint256) private _allTokensIndex;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721.balanceOf(owner), \"ERC721Enumerable: owner index out of bounds\");\n return _ownedTokens[owner][index];\n }\n\n /**\n * @dev See {IERC721Enumerable-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _allTokens.length;\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenByIndex}.\n */\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721Enumerable.totalSupply(), \"ERC721Enumerable: global index out of bounds\");\n return _allTokens[index];\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, tokenId);\n\n if (from == address(0)) {\n _addTokenToAllTokensEnumeration(tokenId);\n } else if (from != to) {\n _removeTokenFromOwnerEnumeration(from, tokenId);\n }\n if (to == address(0)) {\n _removeTokenFromAllTokensEnumeration(tokenId);\n } else if (to != from) {\n _addTokenToOwnerEnumeration(to, tokenId);\n }\n }\n\n /**\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\n * @param to address representing the new owner of the given token ID\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n */\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n uint256 length = ERC721.balanceOf(to);\n _ownedTokens[to][length] = tokenId;\n _ownedTokensIndex[tokenId] = length;\n }\n\n /**\n * @dev Private function to add a token to this extension's token tracking data structures.\n * @param tokenId uint256 ID of the token to be added to the tokens list\n */\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n _allTokensIndex[tokenId] = _allTokens.length;\n _allTokens.push(tokenId);\n }\n\n /**\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n * @param from address representing the previous owner of the given token ID\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n */\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary\n if (tokenIndex != lastTokenIndex) {\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\n\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n }\n\n // This also deletes the contents at the last position of the array\n delete _ownedTokensIndex[tokenId];\n delete _ownedTokens[from][lastTokenIndex];\n }\n\n /**\n * @dev Private function to remove a token from this extension's token tracking data structures.\n * This has O(1) time complexity, but alters the order of the _allTokens array.\n * @param tokenId uint256 ID of the token to be removed from the tokens list\n */\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = _allTokens.length - 1;\n uint256 tokenIndex = _allTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n uint256 lastTokenId = _allTokens[lastTokenIndex];\n\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n // This also deletes the contents at the last position of the array\n delete _allTokensIndex[tokenId];\n _allTokens.pop();\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: balance query for the zero address\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _owners[tokenId];\n require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not owner nor approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n _safeTransfer(from, to, tokenId, _data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _owners[tokenId] != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, _data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId);\n\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId);\n\n // Clear approvals\n _approve(address(0), tokenId);\n\n _balances[owner] -= 1;\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId);\n\n // Clear approvals from the previous owner\n _approve(address(0), tokenId);\n\n _balances[from] -= 1;\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits a {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/AddressManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:legacy\n * @title AddressManager\n * @notice AddressManager is a legacy contract that was used in the old version of the Optimism\n * system to manage a registry of string names to addresses. We now use a more standard\n * proxy system instead, but this contract is still necessary for backwards compatibility\n * with several older contracts.\n */\ncontract AddressManager is Ownable {\n /**\n * @notice Mapping of the hashes of string names to addresses.\n */\n mapping(bytes32 => address) private addresses;\n\n /**\n * @notice Emitted when an address is modified in the registry.\n *\n * @param name String name being set in the registry.\n * @param newAddress Address set for the given name.\n * @param oldAddress Address that was previously set for the given name.\n */\n event AddressSet(string indexed name, address newAddress, address oldAddress);\n\n /**\n * @notice Changes the address associated with a particular name.\n *\n * @param _name String name to associate an address with.\n * @param _address Address to associate with the name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n bytes32 nameHash = _getNameHash(_name);\n address oldAddress = addresses[nameHash];\n addresses[nameHash] = _address;\n\n emit AddressSet(_name, _address, oldAddress);\n }\n\n /**\n * @notice Retrieves the address associated with a given name.\n *\n * @param _name Name to retrieve an address for.\n *\n * @return Address associated with the given name.\n */\n function getAddress(string memory _name) external view returns (address) {\n return addresses[_getNameHash(_name)];\n }\n\n /**\n * @notice Computes the hash of a name.\n *\n * @param _name Name to compute a hash for.\n *\n * @return Hash of the given name.\n */\n function _getNameHash(string memory _name) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(_name));\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\nimport { Proxy } from \"./Proxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\n\n/**\n * @title IStaticERC1967Proxy\n * @notice IStaticERC1967Proxy is a static version of the ERC1967 proxy interface.\n */\ninterface IStaticERC1967Proxy {\n function implementation() external view returns (address);\n\n function admin() external view returns (address);\n}\n\n/**\n * @title IStaticL1ChugSplashProxy\n * @notice IStaticL1ChugSplashProxy is a static version of the ChugSplash proxy interface.\n */\ninterface IStaticL1ChugSplashProxy {\n function getImplementation() external view returns (address);\n\n function getOwner() external view returns (address);\n}\n\n/**\n * @title ProxyAdmin\n * @notice This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy,\n * based on the OpenZeppelin implementation. It has backwards compatibility logic to work\n * with the various types of proxies that have been deployed by Optimism in the past.\n */\ncontract ProxyAdmin is Owned {\n /**\n * @notice The proxy types that the ProxyAdmin can manage.\n *\n * @custom:value ERC1967 Represents an ERC1967 compliant transparent proxy interface.\n * @custom:value CHUGSPLASH Represents the Chugsplash proxy interface (legacy).\n * @custom:value RESOLVED Represents the ResolvedDelegate proxy (legacy).\n */\n enum ProxyType {\n ERC1967,\n CHUGSPLASH,\n RESOLVED\n }\n\n /**\n * @custom:legacy\n * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\n * @custom:legacy\n * @notice A reverse mapping of addresses to names held in the AddressManager. This must be\n * manually kept up to date with changes in the AddressManager for this contract\n * to be able to work as an admin for the ResolvedDelegateProxy type.\n */\n mapping(address => string) public implementationName;\n\n /**\n * @custom:legacy\n * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @custom:legacy\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading = false;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * @notice Sets the proxy type for a given address. Only required for non-standard (legacy)\n * proxy types.\n *\n * @param _address Address of the proxy.\n * @param _type Type of the proxy.\n */\n function setProxyType(address _address, ProxyType _type) external onlyOwner {\n proxyType[_address] = _type;\n }\n\n /**\n * @notice Sets the implementation name for a given address. Only required for\n * ResolvedDelegateProxy type proxies that have an implementation name.\n *\n * @param _address Address of the ResolvedDelegateProxy.\n * @param _name Name of the implementation for the proxy.\n */\n function setImplementationName(address _address, string memory _name) external onlyOwner {\n implementationName[_address] = _name;\n }\n\n /**\n * @notice Set the address of the AddressManager. This is required to manage legacy\n * ResolvedDelegateProxy type proxy contracts.\n *\n * @param _address Address of the AddressManager.\n */\n function setAddressManager(AddressManager _address) external onlyOwner {\n addressManager = _address;\n }\n\n /**\n * @custom:legacy\n * @notice Set an address in the address manager. Since only the owner of the AddressManager\n * can directly modify addresses and the ProxyAdmin will own the AddressManager, this\n * gives the owner of the ProxyAdmin the ability to modify addresses directly.\n *\n * @param _name Name to set within the AddressManager.\n * @param _address Address to attach to the given name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n addressManager.setAddress(_name, _address);\n }\n\n /**\n * @custom:legacy\n * @notice Set the upgrading status for the Chugsplash proxy type.\n *\n * @param _upgrading Whether or not the system is upgrading.\n */\n function setUpgrading(bool _upgrading) external onlyOwner {\n upgrading = _upgrading;\n }\n\n /**\n * @notice Updates the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to update.\n * @param _newAdmin Address of the new proxy admin.\n */\n function changeProxyAdmin(address payable _proxy, address _newAdmin) external onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).changeAdmin(_newAdmin);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setOwner(_newAdmin);\n } else if (ptype == ProxyType.RESOLVED) {\n addressManager.transferOwnership(_newAdmin);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract and delegatecalls the new implementation\n * with some given data. Useful for atomic upgrade-and-initialize calls.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n * @param _data Data to trigger the new implementation with.\n */\n function upgradeAndCall(\n address payable _proxy,\n address _implementation,\n bytes memory _data\n ) external payable onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeToAndCall{ value: msg.value }(_implementation, _data);\n } else {\n // reverts if proxy type is unknown\n upgrade(_proxy, _implementation);\n (bool success, ) = _proxy.call{ value: msg.value }(_data);\n require(success, \"ProxyAdmin: call to proxy after upgrade failed\");\n }\n }\n\n /**\n * @custom:legacy\n * @notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\n *\n * @return Whether or not there is an upgrade going on. May not actually tell you whether an\n * upgrade is going on, since we don't currently plan to use this variable for anything\n * other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\n */\n function isUpgrading() external view returns (bool) {\n return upgrading;\n }\n\n /**\n * @notice Returns the implementation of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the implementation of.\n *\n * @return Address of the implementation of the proxy.\n */\n function getProxyImplementation(address _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).implementation();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getImplementation();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.getAddress(implementationName[_proxy]);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Returns the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the admin of.\n *\n * @return Address of the admin of the proxy.\n */\n function getProxyAdmin(address payable _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).admin();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getOwner();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.owner();\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n */\n function upgrade(address payable _proxy, address _implementation) public onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeTo(_implementation);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setStorage(\n // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,\n bytes32(uint256(uint160(_implementation)))\n );\n } else if (ptype == ProxyType.RESOLVED) {\n string memory name = implementationName[_proxy];\n addressManager.setAddress(name, _implementation);\n } else {\n // It should not be possible to retrieve a ProxyType value which is not matched by\n // one of the previous conditions.\n assert(false);\n }\n }\n}\n" + }, + "@rari-capital/solmate/src/auth/Owned.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol)\nabstract contract Owned {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event OwnerUpdated(address indexed user, address indexed newOwner);\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP STORAGE\n //////////////////////////////////////////////////////////////*/\n\n address public owner;\n\n modifier onlyOwner() virtual {\n require(msg.sender == owner, \"UNAUTHORIZED\");\n\n _;\n }\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(address _owner) {\n owner = _owner;\n\n emit OwnerUpdated(address(0), _owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function setOwner(address newOwner) public virtual onlyOwner {\n owner = newOwner;\n\n emit OwnerUpdated(msg.sender, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Proxy\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\n * if the caller is address(0), meaning that the call originated from an off-chain\n * simulation.\n */\ncontract Proxy {\n /**\n * @notice The storage slot that holds the address of the implementation.\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice The storage slot that holds the address of the owner.\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice An event that is emitted each time the implementation is changed. This event is part\n * of the EIP-1967 specification.\n *\n * @param implementation The address of the implementation contract\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\n * EIP-1967 specification.\n *\n * @param previousAdmin The previous owner of the contract\n * @param newAdmin The new owner of the contract\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\n * eth_call to interact with this proxy without needing to use low-level storage\n * inspection. We assume that nobody is able to trigger calls from address(0) during\n * normal EVM execution.\n */\n modifier proxyCallIfNotAdmin() {\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\n * EIP-1967 admin storage slot so that accidental storage collision with the\n * implementation is not possible.\n *\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\n * transparent proxy interface.\n */\n constructor(address _admin) {\n _changeAdmin(_admin);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Set the implementation contract address. The code at the given address will execute\n * when this contract is called.\n *\n * @param _implementation Address of the implementation contract.\n */\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\n _setImplementation(_implementation);\n }\n\n /**\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\n * atomic execution of initialization-based upgrades.\n *\n * @param _implementation Address of the implementation contract.\n * @param _data Calldata to delegatecall the new implementation with.\n */\n function upgradeToAndCall(address _implementation, bytes calldata _data)\n external\n payable\n proxyCallIfNotAdmin\n returns (bytes memory)\n {\n _setImplementation(_implementation);\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\n require(success, \"Proxy: delegatecall to new implementation contract failed\");\n return returndata;\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _admin New owner of the proxy contract.\n */\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\n _changeAdmin(_admin);\n }\n\n /**\n * @notice Gets the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function admin() external proxyCallIfNotAdmin returns (address) {\n return _getAdmin();\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function implementation() external proxyCallIfNotAdmin returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n emit Upgraded(_implementation);\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _admin New owner of the proxy contract.\n */\n function _changeAdmin(address _admin) internal {\n address previous = _getAdmin();\n assembly {\n sstore(OWNER_KEY, _admin)\n }\n emit AdminChanged(previous, _admin);\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal {\n address impl = _getImplementation();\n require(impl != address(0), \"Proxy: implementation not initialized\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address impl;\n assembly {\n impl := sload(IMPLEMENTATION_KEY)\n }\n return impl;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getAdmin() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/L1ChugSplashProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title IL1ChugSplashDeployer\n */\ninterface IL1ChugSplashDeployer {\n function isUpgrading() external view returns (bool);\n}\n\n/**\n * @custom:legacy\n * @title L1ChugSplashProxy\n * @notice Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added\n * functions `setCode` and `setStorage` for changing the code or storage of the contract.\n *\n * Note for future developers: do NOT make anything in this contract 'public' unless you\n * know what you're doing. Anything public can potentially have a function signature that\n * conflicts with a signature attached to the implementation contract. Public functions\n * SHOULD always have the `proxyCallIfNotOwner` modifier unless there's some *really* good\n * reason not to have that modifier. And there almost certainly is not a good reason to not\n * have that modifier. Beware!\n */\ncontract L1ChugSplashProxy {\n /**\n * @notice \"Magic\" prefix. When prepended to some arbitrary bytecode and used to create a\n * contract, the appended bytecode will be deployed as given.\n */\n bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice Blocks a function from being called when the parent signals that the system should\n * be paused via an isUpgrading function.\n */\n modifier onlyWhenNotPaused() {\n address owner = _getOwner();\n\n // We do a low-level call because there's no guarantee that the owner actually *is* an\n // L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and\n // it turns out that it isn't the right type of contract.\n (bool success, bytes memory returndata) = owner.staticcall(\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector)\n );\n\n // If the call was unsuccessful then we assume that there's no \"isUpgrading\" method and we\n // can just continue as normal. We also expect that the return value is exactly 32 bytes\n // long. If this isn't the case then we can safely ignore the result.\n if (success && returndata.length == 32) {\n // Although the expected value is a *boolean*, it's safer to decode as a uint256 in the\n // case that the isUpgrading function returned something other than 0 or 1. But we only\n // really care about the case where this value is 0 (= false).\n uint256 ret = abi.decode(returndata, (uint256));\n require(ret == 0, \"L1ChugSplashProxy: system is currently being upgraded\");\n }\n\n _;\n }\n\n /**\n * @notice Makes a proxy call instead of triggering the given function when the caller is\n * either the owner or the zero address. Caller can only ever be the zero address if\n * this function is being called off-chain via eth_call, which is totally fine and can\n * be convenient for client-side tooling. Avoids situations where the proxy and\n * implementation share a sighash and the proxy function ends up being called instead\n * of the implementation one.\n *\n * Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If\n * there's a way for someone to send a transaction with msg.sender == address(0) in any\n * real context then we have much bigger problems. Primary reason to include this\n * additional allowed sender is because the owner address can be changed dynamically\n * and we do not want clients to have to keep track of the current owner in order to\n * make an eth_call that doesn't trigger the proxied contract.\n */\n // slither-disable-next-line incorrect-modifier\n modifier proxyCallIfNotOwner() {\n if (msg.sender == _getOwner() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @param _owner Address of the initial contract owner.\n */\n constructor(address _owner) {\n _setOwner(_owner);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Sets the code that should be running behind this proxy.\n *\n * Note: This scheme is a bit different from the standard proxy scheme where one would\n * typically deploy the code separately and then set the implementation address. We're\n * doing it this way because it gives us a lot more freedom on the client side. Can\n * only be triggered by the contract owner.\n *\n * @param _code New contract code to run inside this contract.\n */\n function setCode(bytes memory _code) external proxyCallIfNotOwner {\n // Get the code hash of the current implementation.\n address implementation = _getImplementation();\n\n // If the code hash matches the new implementation then we return early.\n if (keccak256(_code) == _getAccountCodeHash(implementation)) {\n return;\n }\n\n // Create the deploycode by appending the magic prefix.\n bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code);\n\n // Deploy the code and set the new implementation address.\n address newImplementation;\n assembly {\n newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode))\n }\n\n // Check that the code was actually deployed correctly. I'm not sure if you can ever\n // actually fail this check. Should only happen if the contract creation from above runs\n // out of gas but this parent execution thread does NOT run out of gas. Seems like we\n // should be doing this check anyway though.\n require(\n _getAccountCodeHash(newImplementation) == keccak256(_code),\n \"L1ChugSplashProxy: code was not correctly deployed\"\n );\n\n _setImplementation(newImplementation);\n }\n\n /**\n * @notice Modifies some storage slot within the proxy contract. Gives us a lot of power to\n * perform upgrades in a more transparent way. Only callable by the owner.\n *\n * @param _key Storage key to modify.\n * @param _value New value for the storage key.\n */\n function setStorage(bytes32 _key, bytes32 _value) external proxyCallIfNotOwner {\n assembly {\n sstore(_key, _value)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _owner New owner of the proxy contract.\n */\n function setOwner(address _owner) external proxyCallIfNotOwner {\n _setOwner(_owner);\n }\n\n /**\n * @notice Queries the owner of the proxy contract. Can only be called by the owner OR by\n * making an eth_call and setting the \"from\" address to address(0).\n *\n * @return Owner address.\n */\n function getOwner() external proxyCallIfNotOwner returns (address) {\n return _getOwner();\n }\n\n /**\n * @notice Queries the implementation address. Can only be called by the owner OR by making an\n * eth_call and setting the \"from\" address to address(0).\n *\n * @return Implementation address.\n */\n function getImplementation() external proxyCallIfNotOwner returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _owner New owner of the proxy contract.\n */\n function _setOwner(address _owner) internal {\n assembly {\n sstore(OWNER_KEY, _owner)\n }\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal onlyWhenNotPaused {\n address implementation = _getImplementation();\n\n require(implementation != address(0), \"L1ChugSplashProxy: implementation is not set yet\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address implementation;\n assembly {\n implementation := sload(IMPLEMENTATION_KEY)\n }\n return implementation;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getOwner() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n\n /**\n * @notice Gets the code hash for a given account.\n *\n * @param _account Address of the account to get a code hash for.\n *\n * @return Code hash for the account.\n */\n function _getAccountCodeHash(address _account) internal view returns (bytes32) {\n bytes32 codeHash;\n assembly {\n codeHash := extcodehash(_account)\n }\n return codeHash;\n }\n}\n" + }, + "contracts/testing/helpers/ExternalContractCompiler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ProxyAdmin } from \"@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol\";\nimport { Proxy } from \"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\";\n\n/**\n * Just exists so we can compile external contracts.\n */\ncontract ExternalContractCompiler {\n\n}\n" + }, + "contracts/testing/helpers/TestERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\n\ncontract TestERC721 is ERC721 {\n constructor() ERC721(\"TEST\", \"TST\") {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n\n function tokenURI(uint256) public pure virtual override returns (string memory) {}\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 indexed id);\n\n event Approval(address indexed owner, address indexed spender, uint256 indexed id);\n\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE/LOGIC\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n function tokenURI(uint256 id) public view virtual returns (string memory);\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) internal _ownerOf;\n\n mapping(address => uint256) internal _balanceOf;\n\n function ownerOf(uint256 id) public view virtual returns (address owner) {\n require((owner = _ownerOf[id]) != address(0), \"NOT_MINTED\");\n }\n\n function balanceOf(address owner) public view virtual returns (uint256) {\n require(owner != address(0), \"ZERO_ADDRESS\");\n\n return _balanceOf[owner];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) public getApproved;\n\n mapping(address => mapping(address => bool)) public isApprovedForAll;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(string memory _name, string memory _symbol) {\n name = _name;\n symbol = _symbol;\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 id) public virtual {\n address owner = _ownerOf[id];\n\n require(msg.sender == owner || isApprovedForAll[owner][msg.sender], \"NOT_AUTHORIZED\");\n\n getApproved[id] = spender;\n\n emit Approval(owner, spender, id);\n }\n\n function setApprovalForAll(address operator, bool approved) public virtual {\n isApprovedForAll[msg.sender][operator] = approved;\n\n emit ApprovalForAll(msg.sender, operator, approved);\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n require(from == _ownerOf[id], \"WRONG_FROM\");\n\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(\n msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],\n \"NOT_AUTHORIZED\"\n );\n\n // Underflow of the sender's balance is impossible because we check for\n // ownership above and the recipient's balance can't realistically overflow.\n unchecked {\n _balanceOf[from]--;\n\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n delete getApproved[id];\n\n emit Transfer(from, to, id);\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n bytes calldata data\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return\n interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165\n interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721\n interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 id) internal virtual {\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(_ownerOf[id] == address(0), \"ALREADY_MINTED\");\n\n // Counter overflow is incredibly unrealistic.\n unchecked {\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n emit Transfer(address(0), to, id);\n }\n\n function _burn(uint256 id) internal virtual {\n address owner = _ownerOf[id];\n\n require(owner != address(0), \"NOT_MINTED\");\n\n // Ownership check above ensures no underflow.\n unchecked {\n _balanceOf[owner]--;\n }\n\n delete _ownerOf[id];\n\n delete getApproved[id];\n\n emit Transfer(owner, address(0), id);\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL SAFE MINT LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _safeMint(address to, uint256 id) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function _safeMint(\n address to,\n uint256 id,\n bytes memory data\n ) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n}\n\n/// @notice A generic interface for a contract which properly accepts ERC721 tokens.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721TokenReceiver {\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n ) external virtual returns (bytes4) {\n return ERC721TokenReceiver.onERC721Received.selector;\n }\n}\n" + }, + "contracts/testing/helpers/TestERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n constructor() ERC20(\"TEST\", \"TST\", 18) {}\n\n function mint(address to, uint256 value) public {\n _mint(to, value);\n }\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "contracts/L1/TeleportrWithdrawer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AssetReceiver } from \"../universal/AssetReceiver.sol\";\n\n/**\n * @notice Stub interface for Teleportr.\n */\ninterface Teleportr {\n function withdrawBalance() external;\n}\n\n/**\n * @title TeleportrWithdrawer\n * @notice The TeleportrWithdrawer is a simple contract capable of withdrawing funds from the\n * TeleportrContract and sending them to some recipient address.\n */\ncontract TeleportrWithdrawer is AssetReceiver {\n /**\n * @notice Address of the Teleportr contract.\n */\n address public teleportr;\n\n /**\n * @notice Address that will receive Teleportr withdrawals.\n */\n address public recipient;\n\n /**\n * @notice Data to be sent to the recipient address.\n */\n bytes public data;\n\n /**\n * @param _owner Initial owner of the contract.\n */\n constructor(address _owner) AssetReceiver(_owner) {}\n\n /**\n * @notice Allows the owner to update the recipient address.\n *\n * @param _recipient New recipient address.\n */\n function setRecipient(address _recipient) external onlyOwner {\n recipient = _recipient;\n }\n\n /**\n * @notice Allows the owner to update the Teleportr contract address.\n *\n * @param _teleportr New Teleportr contract address.\n */\n function setTeleportr(address _teleportr) external onlyOwner {\n teleportr = _teleportr;\n }\n\n /**\n * @notice Allows the owner to update the data to be sent to the recipient address.\n *\n * @param _data New data to be sent to the recipient address.\n */\n function setData(bytes memory _data) external onlyOwner {\n data = _data;\n }\n\n /**\n * @notice Withdraws the full balance of the Teleportr contract to the recipient address.\n * Anyone is allowed to trigger this function since the recipient address cannot be\n * controlled by the msg.sender.\n */\n function withdrawFromTeleportr() external {\n Teleportr(teleportr).withdrawBalance();\n (bool success, ) = recipient.call{ value: address(this).balance }(data);\n require(success, \"TeleportrWithdrawer: send failed\");\n }\n}\n" + }, + "contracts/universal/AssetReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\nimport { Transactor } from \"./Transactor.sol\";\n\n/**\n * @title AssetReceiver\n * @notice AssetReceiver is a minimal contract for receiving funds assets in the form of either\n * ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.\n */\ncontract AssetReceiver is Transactor {\n /**\n * @notice Emitted when ETH is received by this address.\n *\n * @param from Address that sent ETH to this contract.\n * @param amount Amount of ETH received.\n */\n event ReceivedETH(address indexed from, uint256 amount);\n\n /**\n * @notice Emitted when ETH is withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param amount ETH amount withdrawn.\n */\n event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param amount ERC20 amount withdrawn.\n */\n event WithdrewERC20(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 amount\n );\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param id Token ID being withdrawn.\n */\n event WithdrewERC721(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 id\n );\n\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Transactor(_owner) {}\n\n /**\n * @notice Make sure we can receive ETH.\n */\n receive() external payable {\n emit ReceivedETH(msg.sender, msg.value);\n }\n\n /**\n * @notice Withdraws full ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n */\n function withdrawETH(address payable _to) external onlyOwner {\n withdrawETH(_to, address(this).balance);\n }\n\n /**\n * @notice Withdraws partial ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n * @param _amount Amount of ETH to withdraw.\n */\n function withdrawETH(address payable _to, uint256 _amount) public onlyOwner {\n // slither-disable-next-line reentrancy-unlimited-gas\n (bool success, ) = _to.call{ value: _amount }(\"\");\n emit WithdrewETH(msg.sender, _to, _amount);\n }\n\n /**\n * @notice Withdraws full ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n */\n function withdrawERC20(ERC20 _asset, address _to) external onlyOwner {\n withdrawERC20(_asset, _to, _asset.balanceOf(address(this)));\n }\n\n /**\n * @notice Withdraws partial ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n * @param _amount Amount of ERC20 to withdraw.\n */\n function withdrawERC20(\n ERC20 _asset,\n address _to,\n uint256 _amount\n ) public onlyOwner {\n // slither-disable-next-line unchecked-transfer\n _asset.transfer(_to, _amount);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC20(msg.sender, _to, address(_asset), _amount);\n }\n\n /**\n * @notice Withdraws ERC721 token to the recipient.\n *\n * @param _asset ERC721 token to withdraw.\n * @param _to Address to receive the ERC721 token.\n * @param _id Token ID of the ERC721 token to withdraw.\n */\n function withdrawERC721(\n ERC721 _asset,\n address _to,\n uint256 _id\n ) external onlyOwner {\n _asset.transferFrom(address(this), _to, _id);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC721(msg.sender, _to, address(_asset), _id);\n }\n}\n" + }, + "contracts/universal/Transactor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\n\n/**\n * @title Transactor\n * @notice Transactor is a minimal contract that can send transactions.\n */\ncontract Transactor is Owned {\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * Sends a CALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n * @param _value ETH value to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function CALL(\n address _target,\n bytes memory _data,\n uint256 _value\n ) external payable onlyOwner returns (bool, bytes memory) {\n return _target.call{ value: _value }(_data);\n }\n\n /**\n * Sends a DELEGATECALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function DELEGATECALL(address _target, bytes memory _data)\n external\n payable\n onlyOwner\n returns (bool, bytes memory)\n {\n // slither-disable-next-line controlled-delegatecall\n return _target.delegatecall(_data);\n }\n}\n" + }, + "contracts/L2/TeleportrDisburser.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title TeleportrDisburser\n */\ncontract TeleportrDisburser is Ownable {\n /**\n * @notice A struct holding the address and amount to disbursement.\n */\n struct Disbursement {\n uint256 amount;\n address addr;\n }\n\n /**\n * @notice Total number of disbursements processed.\n */\n uint256 public totalDisbursements;\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a disbursement is successfuly sent.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The recipient of the disbursement.\n * @param amount The amount sent to the recipient.\n */\n event DisbursementSuccess(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @notice Emitted any time a disbursement fails to send.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The intended recipient of the disbursement.\n * @param amount The amount intended to be sent to the recipient.\n */\n event DisbursementFailed(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @custom:semver 0.0.1\n */\n constructor() {\n totalDisbursements = 0;\n }\n\n /**\n * @notice Accepts a list of Disbursements and forwards the amount paid to the contract to each\n * recipient. Reverts if there are zero disbursements, the total amount to forward\n * differs from the amount sent in the transaction, or the _nextDepositId is\n * unexpected. Failed disbursements will not cause the method to revert, but will\n * instead be held by the contract and available for the owner to withdraw.\n *\n * @param _nextDepositId The depositId of the first Dispursement.\n * @param _disbursements A list of Disbursements to process.\n */\n function disburse(uint256 _nextDepositId, Disbursement[] calldata _disbursements)\n external\n payable\n onlyOwner\n {\n // Ensure there are disbursements to process.\n uint256 _numDisbursements = _disbursements.length;\n require(_numDisbursements > 0, \"No disbursements\");\n\n // Ensure the _nextDepositId matches our expected value.\n uint256 _depositId = totalDisbursements;\n require(_depositId == _nextDepositId, \"Unexpected next deposit id\");\n unchecked {\n totalDisbursements += _numDisbursements;\n }\n\n // Ensure the amount sent in the transaction is equal to the sum of the\n // disbursements.\n uint256 _totalDisbursed = 0;\n for (uint256 i = 0; i < _numDisbursements; i++) {\n _totalDisbursed += _disbursements[i].amount;\n }\n require(_totalDisbursed == msg.value, \"Disbursement total != amount sent\");\n\n // Process disbursements.\n for (uint256 i = 0; i < _numDisbursements; i++) {\n uint256 _amount = _disbursements[i].amount;\n address _addr = _disbursements[i].addr;\n\n // Deliver the dispursement amount to the receiver. If the\n // disbursement fails, the amount will be kept by the contract\n // rather than reverting to prevent blocking progress on other\n // disbursements.\n\n // slither-disable-next-line calls-loop,reentrancy-events\n (bool success, ) = _addr.call{ value: _amount, gas: 2300 }(\"\");\n if (success) emit DisbursementSuccess(_depositId, _addr, _amount);\n else emit DisbursementFailed(_depositId, _addr, _amount);\n\n unchecked {\n _depositId += 1;\n }\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 balance = address(this).balance;\n emit BalanceWithdrawn(_owner, balance);\n payable(_owner).transfer(balance);\n }\n}\n" + }, + "contracts/L1/TeleportrDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:attribution https://github.com/0xclem/teleportr\n * @title TeleportrDeposit\n * @notice A contract meant to manage deposits into Optimism's Teleportr custodial bridge. Deposits\n * are rate limited to avoid a situation where too much ETH is flowing through this bridge\n * and cannot be properly disbursed on L2. Inspired by 0xclem's original Teleportr system\n * (https://github.com/0xclem/teleportr).\n */\ncontract TeleportrDeposit is Ownable {\n /**\n * @notice Minimum deposit amount (in wei).\n */\n uint256 public minDepositAmount;\n\n /**\n * @notice Maximum deposit amount (in wei).\n */\n uint256 public maxDepositAmount;\n\n /**\n * @notice Maximum balance this contract will hold before it starts rejecting deposits.\n */\n uint256 public maxBalance;\n\n /**\n * @notice Total number of deposits received.\n */\n uint256 public totalDeposits;\n\n /**\n * @notice Emitted any time the minimum deposit amount is set.\n *\n * @param previousAmount The previous minimum deposit amount.\n * @param newAmount The new minimum deposit amount.\n */\n event MinDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the maximum deposit amount is set.\n *\n * @param previousAmount The previous maximum deposit amount.\n * @param newAmount The new maximum deposit amount.\n */\n event MaxDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the contract maximum balance is set.\n *\n * @param previousBalance The previous maximum contract balance.\n * @param newBalance The new maximum contract balance.\n */\n event MaxBalanceSet(uint256 previousBalance, uint256 newBalance);\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a successful deposit is received.\n *\n * @param depositId A unique sequencer number identifying the deposit.\n * @param emitter The sending address of the payer.\n * @param amount The amount deposited by the payer.\n */\n event EtherReceived(uint256 indexed depositId, address indexed emitter, uint256 indexed amount);\n\n /**\n * @custom:semver 0.0.1\n *\n * @param _minDepositAmount The initial minimum deposit amount.\n * @param _maxDepositAmount The initial maximum deposit amount.\n * @param _maxBalance The initial maximum contract balance.\n */\n constructor(\n uint256 _minDepositAmount,\n uint256 _maxDepositAmount,\n uint256 _maxBalance\n ) {\n minDepositAmount = _minDepositAmount;\n maxDepositAmount = _maxDepositAmount;\n maxBalance = _maxBalance;\n totalDeposits = 0;\n emit MinDepositAmountSet(0, _minDepositAmount);\n emit MaxDepositAmountSet(0, _maxDepositAmount);\n emit MaxBalanceSet(0, _maxBalance);\n }\n\n /**\n * @notice Accepts deposits that will be disbursed to the sender's address on L2.\n */\n receive() external payable {\n require(msg.value >= minDepositAmount, \"Deposit amount is too small\");\n require(msg.value <= maxDepositAmount, \"Deposit amount is too big\");\n require(address(this).balance <= maxBalance, \"Contract max balance exceeded\");\n\n emit EtherReceived(totalDeposits, msg.sender, msg.value);\n unchecked {\n totalDeposits += 1;\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 _balance = address(this).balance;\n emit BalanceWithdrawn(_owner, _balance);\n payable(_owner).transfer(_balance);\n }\n\n /**\n * @notice Sets the minimum amount that can be deposited in a receive.\n *\n * @param _minDepositAmount The new minimum deposit amount.\n */\n function setMinAmount(uint256 _minDepositAmount) external onlyOwner {\n emit MinDepositAmountSet(minDepositAmount, _minDepositAmount);\n minDepositAmount = _minDepositAmount;\n }\n\n /**\n * @notice Sets the maximum amount that can be deposited in a receive.\n *\n * @param _maxDepositAmount The new maximum deposit amount.\n */\n function setMaxAmount(uint256 _maxDepositAmount) external onlyOwner {\n emit MaxDepositAmountSet(maxDepositAmount, _maxDepositAmount);\n maxDepositAmount = _maxDepositAmount;\n }\n\n /**\n * @notice Sets the maximum balance the contract can hold after a receive.\n *\n * @param _maxBalance The new maximum contract balance.\n */\n function setMaxBalance(uint256 _maxBalance) external onlyOwner {\n emit MaxBalanceSet(maxBalance, _maxBalance);\n maxBalance = _maxBalance;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/kovan/L1ERC721Bridge.json b/packages/contracts-periphery/deployments/kovan/L1ERC721Bridge.json deleted file mode 100644 index fd84f54923117..0000000000000 --- a/packages/contracts-periphery/deployments/kovan/L1ERC721Bridge.json +++ /dev/null @@ -1,686 +0,0 @@ -{ - "address": "0x7c2d4c855141f06700a4a5EE49FC7D77758ECa43", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_messenger", - "type": "address" - }, - { - "internalType": "address", - "name": "_otherBridge", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC721BridgeFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC721BridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "MAJOR_VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MINOR_VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PATCH_VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "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" - } - ], - "name": "bridgeERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "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" - } - ], - "name": "bridgeERC721To", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "deposits", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "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" - } - ], - "name": "finalizeBridgeERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_messenger", - "type": "address" - }, - { - "internalType": "address", - "name": "_otherBridge", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "messenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "otherBridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x4dbc72e324d8986993923efa70597dd1a7bea0674e8bf3b52e09b88a7be198ea", - "receipt": { - "to": null, - "from": "0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5", - "contractAddress": "0x7c2d4c855141f06700a4a5EE49FC7D77758ECa43", - "transactionIndex": 2, - "gasUsed": "1312270", - "logsBloom": "0x00000000000000010000000000000000000000000000000000800001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000080000000000000000000000000000080000000020000000000000000001000000000000000000400000000000000000000000000000000000000000000000000000000008000040000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x228fd3414810ad7d17f1dd2c1969f1423c53759366e06fec5df3892d180bb75c", - "transactionHash": "0x4dbc72e324d8986993923efa70597dd1a7bea0674e8bf3b52e09b88a7be198ea", - "logs": [ - { - "transactionIndex": 2, - "blockNumber": 32495144, - "transactionHash": "0x4dbc72e324d8986993923efa70597dd1a7bea0674e8bf3b52e09b88a7be198ea", - "address": "0x7c2d4c855141f06700a4a5EE49FC7D77758ECa43", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000c37f6a6c4ab335e20d10f034b90386e2fb70bbf5" - ], - "data": "0x", - "logIndex": 20, - "blockHash": "0x228fd3414810ad7d17f1dd2c1969f1423c53759366e06fec5df3892d180bb75c" - }, - { - "transactionIndex": 2, - "blockNumber": 32495144, - "transactionHash": "0x4dbc72e324d8986993923efa70597dd1a7bea0674e8bf3b52e09b88a7be198ea", - "address": "0x7c2d4c855141f06700a4a5EE49FC7D77758ECa43", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 21, - "blockHash": "0x228fd3414810ad7d17f1dd2c1969f1423c53759366e06fec5df3892d180bb75c" - } - ], - "blockNumber": 32495144, - "cumulativeGasUsed": "1953428", - "status": 1, - "byzantium": true - }, - "args": [ - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000" - ], - "numDeployments": 2, - "solcInputHash": "c6fd6c61d1988656e270189e3651a1e1", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAJOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PATCH_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"bridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}],\"name\":\"bridgeERC721To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"finalizeBridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"ERC721BridgeFinalized(address,address,address,address,uint256,bytes)\":{\"params\":{\"extraData\":\"Extra data for use on the client-side.\",\"from\":\"Address that initiated bridging action.\",\"localToken\":\"Address of the token on this domain.\",\"remoteToken\":\"Address of the token on the remote domain.\",\"to\":\"Address to receive the token.\",\"tokenId\":\"ID of the specific token deposited.\"}},\"ERC721BridgeInitiated(address,address,address,address,uint256,bytes)\":{\"params\":{\"extraData\":\"Extra data for use on the client-side.\",\"from\":\"Address that initiated bridging action.\",\"localToken\":\"Address of the token on this domain.\",\"remoteToken\":\"Address of the token on the remote domain.\",\"to\":\"Address to receive the token.\",\"tokenId\":\"ID of the specific token deposited.\"}}},\"kind\":\"dev\",\"methods\":{\"bridgeERC721(address,address,uint256,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.\",\"_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 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.\",\"_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.\",\"_otherBridge\":\"Address of the ERC721 bridge on the other 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,address)\":{\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\",\"_otherBridge\":\"Address of the ERC721 bridge on the other network.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"L1ERC721Bridge\",\"version\":1},\"userdoc\":{\"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.\"}},\"kind\":\"user\",\"methods\":{\"MAJOR_VERSION()\":{\"notice\":\"Contract version number (major).\"},\"MINOR_VERSION()\":{\"notice\":\"Contract version number (minor).\"},\"PATCH_VERSION()\":{\"notice\":\"Contract version number (patch).\"},\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to the caller's account on L2.\"},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to some recipient's account on L2.\"},\"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.\"},\"otherBridge()\":{\"notice\":\"Address of the bridge on the other network.\"}},\"notice\":\"The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to make it possible to transfer ERC721 tokens between Optimism and Ethereum. This contract acts as an escrow for ERC721 tokens deposted into L2.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1/messaging/L1ERC721Bridge.sol\":\"L1ERC721Bridge\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.9.0;\\n\\n/* Interface Imports */\\nimport { ICrossDomainMessenger } from \\\"./ICrossDomainMessenger.sol\\\";\\n\\n/**\\n * @title CrossDomainEnabled\\n * @dev Helper contract for contracts performing cross-domain communications\\n *\\n * Compiler used: defined by inheriting contract\\n */\\ncontract CrossDomainEnabled {\\n /*************\\n * Variables *\\n *************/\\n\\n // Messenger contract used to send and recieve messages from the other domain.\\n address public messenger;\\n\\n /***************\\n * Constructor *\\n ***************/\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on the current layer.\\n */\\n constructor(address _messenger) {\\n messenger = _messenger;\\n }\\n\\n /**********************\\n * Function Modifiers *\\n **********************/\\n\\n /**\\n * Enforces that the modified function is only callable by a specific cross-domain account.\\n * @param _sourceDomainAccount The only account on the originating domain which is\\n * authenticated to call this function.\\n */\\n modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) {\\n require(\\n msg.sender == address(getCrossDomainMessenger()),\\n \\\"OVM_XCHAIN: messenger contract unauthenticated\\\"\\n );\\n\\n require(\\n getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount,\\n \\\"OVM_XCHAIN: wrong sender of cross-domain message\\\"\\n );\\n\\n _;\\n }\\n\\n /**********************\\n * Internal Functions *\\n **********************/\\n\\n /**\\n * Gets the messenger, usually from storage. This function is exposed in case a child contract\\n * needs to override.\\n * @return The address of the cross-domain messenger contract which should be used.\\n */\\n function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {\\n return ICrossDomainMessenger(messenger);\\n }\\n\\n /**q\\n * Sends a message to an account on another domain\\n * @param _crossDomainTarget The intended recipient on the destination domain\\n * @param _message The data to send to the target (usually calldata to a function with\\n * `onlyFromCrossDomainAccount()`)\\n * @param _gasLimit The gasLimit for the receipt of the message on the target domain.\\n */\\n function sendCrossDomainMessage(\\n address _crossDomainTarget,\\n uint32 _gasLimit,\\n bytes memory _message\\n ) internal {\\n // slither-disable-next-line reentrancy-events, reentrancy-benign\\n getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);\\n }\\n}\\n\",\"keccak256\":\"0x9c3cc8b7047c68a403529b15769a21c2e2668ea71db7bef51f123288009811ea\",\"license\":\"MIT\"},\"@eth-optimism/contracts/contracts/libraries/bridge/ICrossDomainMessenger.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.9.0;\\n\\n/**\\n * @title ICrossDomainMessenger\\n */\\ninterface ICrossDomainMessenger {\\n /**********\\n * Events *\\n **********/\\n\\n event SentMessage(\\n address indexed target,\\n address sender,\\n bytes message,\\n uint256 messageNonce,\\n uint256 gasLimit\\n );\\n event RelayedMessage(bytes32 indexed msgHash);\\n event FailedRelayedMessage(bytes32 indexed msgHash);\\n\\n /*************\\n * Variables *\\n *************/\\n\\n function xDomainMessageSender() external view returns (address);\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * Sends a cross domain message to the target messenger.\\n * @param _target Target contract address.\\n * @param _message Message to send to the target.\\n * @param _gasLimit Gas limit for the provided message.\\n */\\n function sendMessage(\\n address _target,\\n bytes calldata _message,\\n uint32 _gasLimit\\n ) external;\\n}\\n\",\"keccak256\":\"0x8f29ae23021345a20ccac7b5edb3fc38268aef943b65adc8a32e74b80bf1833a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x652fee292f698d8dba81bf287cb71f1682f6483b67ebe601a5f7387dcfc30b34\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = _setInitializedVersion(1);\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\\n * initialization step. This is essential to configure modules that are added through upgrades and that require\\n * initialization.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n */\\n modifier reinitializer(uint8 version) {\\n bool isTopLevelCall = _setInitializedVersion(version);\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(version);\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n */\\n function _disableInitializers() internal virtual {\\n _setInitializedVersion(type(uint8).max);\\n }\\n\\n function _setInitializedVersion(uint8 version) private returns (bool) {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\\n // of initializers, because in other contexts the contract may have been reentered.\\n if (_initializing) {\\n require(\\n version == 1 && !AddressUpgradeable.isContract(address(this)),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n return false;\\n } else {\\n require(_initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n return true;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7454006cccb737612b00104d2f606d728e2818b778e7e55542f063c614ce46ba\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55cf2bd9fc76704ddcdc19834cd288b7de00fc0f298a40ea16a954ae8991db2d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/L1/messaging/L1ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport {\\n CrossDomainEnabled\\n} from \\\"@eth-optimism/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport { IERC721 } from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { L2ERC721Bridge } from \\\"../../L2/messaging/L2ERC721Bridge.sol\\\";\\nimport { Semver } from \\\"../../universal/Semver.sol\\\";\\n\\n/**\\n * @title L1ERC721Bridge\\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens between Optimism and Ethereum. This contract\\n * acts as an escrow for ERC721 tokens deposted into L2.\\n */\\ncontract L1ERC721Bridge is Semver, CrossDomainEnabled, OwnableUpgradeable {\\n /**\\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeInitiated(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFinalized(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Address of the bridge on the other network.\\n */\\n address public otherBridge;\\n\\n // Maps L1 token to L2 token to token ID to a boolean indicating if the token is deposited\\n /**\\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\\n * by ID was deposited for a given L2 token.\\n */\\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(0, 0, 1)\\n CrossDomainEnabled(address(0))\\n {\\n initialize(_messenger, _otherBridge);\\n }\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n function initialize(address _messenger, address _otherBridge) public initializer {\\n messenger = _messenger;\\n otherBridge = _otherBridge;\\n\\n // Initialize upgradable OZ contracts\\n __Ownable_init();\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to the caller's account on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function bridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n // Modifier requiring sender to be EOA. This check could be bypassed by a malicious\\n // contract via initcode, but it takes care of the user error we want to avoid.\\n require(!Address.isContract(msg.sender), \\\"L1ERC721Bridge: account is not externally owned\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n msg.sender,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to some recipient's account on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function bridgeERC721To(\\n address _localToken,\\n address _remoteToken,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n _to,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /*************************\\n * Cross-chain Functions *\\n *************************/\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyFromCrossDomainAccount(otherBridge) {\\n // Checks that the L1/L2 token pair has a token ID that is escrowed in the L1 Bridge\\n require(\\n deposits[_localToken][_remoteToken][_tokenId] == true,\\n \\\"Token ID is not escrowed in the L1 Bridge\\\"\\n );\\n\\n deposits[_localToken][_remoteToken][_tokenId] = false;\\n\\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the withdrawer\\n // slither-disable-next-line reentrancy-events\\n IERC721(_localToken).transferFrom(address(this), _to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @notice Internal function for initiating a token bridge to the other domain.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _from Address of the sender on this domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal {\\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\\n bytes memory message = abi.encodeWithSelector(\\n L2ERC721Bridge.finalizeBridgeERC721.selector,\\n _remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Lock token into bridge\\n deposits[_localToken][_remoteToken][_tokenId] = true;\\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\\n\\n // Send calldata into L2\\n sendCrossDomainMessage(otherBridge, _minGasLimit, message);\\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0x6eb7efcb31944c40f6ceb1536d1928e88092339dd010ae137fa6934ba5dd47a7\",\"license\":\"MIT\"},\"contracts/L2/messaging/L2ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport {\\n CrossDomainEnabled\\n} from \\\"@eth-optimism/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport { ERC165Checker } from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { L1ERC721Bridge } from \\\"../../L1/messaging/L1ERC721Bridge.sol\\\";\\nimport { IOptimismMintableERC721 } from \\\"../../universal/op-erc721/IOptimismMintableERC721.sol\\\";\\nimport { Semver } from \\\"../../universal/Semver.sol\\\";\\n\\n/**\\n * @title L2ERC721Bridge\\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens between Optimism and Ethereum. This contract\\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\\n * This contract also acts as a burner for tokens being withdrawn.\\n */\\ncontract L2ERC721Bridge is Semver, CrossDomainEnabled, OwnableUpgradeable {\\n /**\\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeInitiated(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFinalized(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network fails.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFailed(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Address of the bridge on the other network.\\n */\\n address public otherBridge;\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(0, 0, 1)\\n CrossDomainEnabled(address(0))\\n {\\n initialize(_messenger, _otherBridge);\\n }\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n function initialize(address _messenger, address _otherBridge) public initializer {\\n messenger = _messenger;\\n otherBridge = _otherBridge;\\n\\n // Initialize upgradable OZ contracts\\n __Ownable_init();\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to the caller's account on L1.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function bridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n // Modifier requiring sender to be EOA. This check could be bypassed by a malicious\\n // contract via initcode, but it takes care of the user error we want to avoid.\\n require(!Address.isContract(msg.sender), \\\"L2ERC721Bridge: account is not externally owned\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n msg.sender,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to some recipient's account on L1.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function bridgeERC721To(\\n address _localToken,\\n address _remoteToken,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n _to,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyFromCrossDomainAccount(otherBridge) {\\n // Check the target token is compliant and verify the deposited token on L1 matches the L2\\n // deposited token representation.\\n if (\\n // slither-disable-next-line reentrancy-events\\n ERC165Checker.supportsInterface(\\n _localToken,\\n type(IOptimismMintableERC721).interfaceId\\n ) && _remoteToken == IOptimismMintableERC721(_localToken).remoteToken()\\n ) {\\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\\n // on L2.\\n // slither-disable-next-line reentrancy-events\\n IOptimismMintableERC721(_localToken).mint(_to, _tokenId);\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n } else {\\n // Either the L2 token which is being deposited-into disagrees about the correct address\\n // of its L1 token, or does not support the correct interface.\\n // This should only happen if there is a malicious L2 token, or if a user somehow\\n // specified the wrong L2 token address to deposit into.\\n // In either case, we stop the process here and construct a withdrawal\\n // message so that users can get their NFT out in some cases.\\n // There is no way to prevent malicious token contracts altogether, but this does limit\\n // user error and mitigate some forms of malicious contract behavior.\\n bytes memory message = abi.encodeWithSelector(\\n L1ERC721Bridge.finalizeBridgeERC721.selector,\\n _remoteToken,\\n _localToken,\\n _to, // switched the _to and _from here to bounce back the deposit to the sender\\n _from,\\n _tokenId,\\n _extraData\\n );\\n\\n // Send message up to L1 bridge\\n // slither-disable-next-line reentrancy-events\\n sendCrossDomainMessage(otherBridge, 0, message);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFailed(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n }\\n\\n /**\\n * @notice Internal function for initiating a token bridge to the other domain.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _from Address of the sender on this domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal {\\n // Check that the withdrawal is being initiated by the NFT owner\\n require(\\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\\n \\\"Withdrawal is not being initiated by NFT owner\\\"\\n );\\n\\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\\n // usage\\n // slither-disable-next-line reentrancy-events\\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\\n\\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\\n // slither-disable-next-line reentrancy-events\\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\\n require(\\n remoteToken == _remoteToken,\\n \\\"L2ERC721Bridge: remote token does not match given value\\\"\\n );\\n\\n bytes memory message = abi.encodeWithSelector(\\n L1ERC721Bridge.finalizeBridgeERC721.selector,\\n remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Send message to L1 bridge\\n // slither-disable-next-line reentrancy-events\\n sendCrossDomainMessage(otherBridge, _minGasLimit, message);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0xc03d61745dc6c8ddaae46667c8d092121847a7b6d9c9381a47cf1a5d75ba47f4\",\"license\":\"MIT\"},\"contracts/universal/Semver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Semver\\n * @notice Semver is a simple contract for managing contract versions.\\n */\\ncontract Semver {\\n /**\\n * @notice Contract version number (major).\\n */\\n uint256 public immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 public immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\n uint256 public immutable PATCH_VERSION;\\n\\n /**\\n * @param _major Version number (major).\\n * @param _minor Version number (minor).\\n * @param _patch Version number (patch).\\n */\\n constructor(\\n uint256 _major,\\n uint256 _minor,\\n uint256 _patch\\n ) {\\n MAJOR_VERSION = _major;\\n MINOR_VERSION = _minor;\\n PATCH_VERSION = _patch;\\n }\\n}\\n\",\"keccak256\":\"0x3a1b68a00fab786f42cc163b59fa8689ca3a2eee46114f3543e1f2ece1f78abb\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/IOptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport {\\n IERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\\\";\\n\\n/**\\n * @title IOptimismMintableERC721\\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\\n */\\ninterface IOptimismMintableERC721 is IERC721Enumerable {\\n /**\\n * @notice Emitted when a token is minted.\\n *\\n * @param account Address of the account the token was minted to.\\n * @param tokenId Token ID of the minted token.\\n */\\n event Mint(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Emitted when a token is burned.\\n *\\n * @param account Address of the account the token was burned from.\\n * @param tokenId Token ID of the burned token.\\n */\\n event Burn(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Chain ID of the chain where the remote token is deployed.\\n */\\n function remoteChainId() external returns (uint256);\\n\\n /**\\n * @notice Address of the token on the remote domain.\\n */\\n function remoteToken() external returns (address);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n function bridge() external returns (address);\\n\\n /**\\n * @notice Mints some token ID for a user.\\n *\\n * @param _to Address of the user to mint the token for.\\n * @param _tokenId Token ID to mint.\\n */\\n function mint(address _to, uint256 _tokenId) external;\\n\\n /**\\n * @notice Burns a token ID from a user.\\n *\\n * @param _from Address of the user to burn the token from.\\n * @param _tokenId Token ID to burn.\\n */\\n function burn(address _from, uint256 _tokenId) external;\\n}\\n\",\"keccak256\":\"0xad2e31bc9a8456a2f604749b0acc3f8882ff8c984f4d842b9e284dd1947439f3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620019ee380380620019ee83398101604081905262000034916200038a565b6000608081905260a0819052600160c05280546001600160a01b03191690556200005f828262000067565b5050620003c2565b60006200007560016200011a565b9050801562000092576000805460ff60a81b1916600160a81b1790555b600080546001600160a01b038086166001600160a01b0319928316179092556065805492851692909116919091179055620000cc62000244565b801562000115576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60008054600160a81b900460ff1615620001b5578160ff1660011480156200015557506200015330620002ae60201b62000ab31760201c565b155b620001ad5760405162461bcd60e51b815260206004820152602e6024820152600080516020620019ae83398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b506000919050565b60005460ff808416600160a01b90920416106200021b5760405162461bcd60e51b815260206004820152602e6024820152600080516020620019ae83398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620001a4565b506000805460ff909216600160a01b0260ff60a01b19909216919091179055600190565b919050565b600054600160a81b900460ff16620002a25760405162461bcd60e51b815260206004820152602b6024820152600080516020620019ce83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620001a4565b620002ac620002bd565b565b6001600160a01b03163b151590565b600054600160a81b900460ff166200031b5760405162461bcd60e51b815260206004820152602b6024820152600080516020620019ce83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620001a4565b620002ac33603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200023f57600080fd5b600080604083850312156200039e57600080fd5b620003a98362000372565b9150620003b96020840162000372565b90509250929050565b60805160a05160c0516115bc620003f2600039600061019f015260006102400152600061027a01526115bc6000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c8063761f44931161008c578063c89701a211610066578063c89701a21461021b578063c8b915311461023b578063f2fde38b14610262578063f786becd1461027557600080fd5b8063761f4493146101d75780638da5cb5b146101ea578063aa5574521461020857600080fd5b80635d93a3fc116100bd5780635d93a3fc146101565780636bf2606a1461019a578063715018a6146101cf57600080fd5b80633687011a146100e45780633cb747bf146100f9578063485cc95514610143575b600080fd5b6100f76100f23660046111b4565b61029c565b005b6000546101199073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f7610151366004611237565b610348565b61018a610164366004611270565b606660209081526000938452604080852082529284528284209052825290205460ff1681565b604051901515815260200161013a565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161013a565b6100f7610462565b6100f76101e53660046112b1565b6104ef565b60335473ffffffffffffffffffffffffffffffffffffffff16610119565b6100f7610216366004611349565b61096a565b6065546101199073ffffffffffffffffffffffffffffffffffffffff1681565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b6100f76102703660046113c0565b610983565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b333b15610330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4c314552433732314272696467653a206163636f756e74206973206e6f74206560448201527f787465726e616c6c79206f776e6564000000000000000000000000000000000060648201526084015b60405180910390fd5b6103408686333388888888610acf565b505050505050565b60006103546001610d00565b9050801561039d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b6000805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560658054928516929091169190911790556103fa610ecf565b801561045d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146104e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610327565b6104ed6000610f82565b565b60655473ffffffffffffffffffffffffffffffffffffffff1661052760005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610327565b8073ffffffffffffffffffffffffffffffffffffffff1661061760005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561065c57600080fd5b505afa158015610670573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069491906113e4565b73ffffffffffffffffffffffffffffffffffffffff1614610737576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610327565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152606660209081526040808320938b1683529281528282208783529052205460ff161515600114610806576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f546f6b656e204944206973206e6f7420657363726f77656420696e207468652060448201527f4c312042726964676500000000000000000000000000000000000000000000006064820152608401610327565b73ffffffffffffffffffffffffffffffffffffffff88811660008181526066602090815260408083208c8616845282528083208984529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152918716602483015260448201869052906323b872dd90606401600060405180830381600087803b1580156108c657600080fd5b505af11580156108da573d6000803e3d6000fd5b505050508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac88888888604051610958949392919061144a565b60405180910390a45050505050505050565b61097a8787338888888888610acf565b50505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610a04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610327565b73ffffffffffffffffffffffffffffffffffffffff8116610aa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610327565b610ab081610f82565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600063761f449360e01b888a8989898888604051602401610af6979695949392919061148a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152606686528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610c3657600080fd5b505af1158015610c4a573d6000803e3d6000fd5b5050606554610c73925073ffffffffffffffffffffffffffffffffffffffff1690508583610ff9565b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610ced949392919061144a565b60405180910390a4505050505050505050565b600080547501000000000000000000000000000000000000000000900460ff1615610dcb578160ff166001148015610d375750303b155b610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610327565b506000919050565b60005460ff808416740100000000000000000000000000000000000000009092041610610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610327565b506000805460ff90921674010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055600190565b919050565b6000547501000000000000000000000000000000000000000000900460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610327565b6104ed611081565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b90611053908690859087906004016114e7565b600060405180830381600087803b15801561106d57600080fd5b505af115801561097a573d6000803e3d6000fd5b6000547501000000000000000000000000000000000000000000900460ff1661112c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610327565b6104ed33610f82565b73ffffffffffffffffffffffffffffffffffffffff81168114610ab057600080fd5b803563ffffffff81168114610eca57600080fd5b60008083601f84011261117d57600080fd5b50813567ffffffffffffffff81111561119557600080fd5b6020830191508360208285010111156111ad57600080fd5b9250929050565b60008060008060008060a087890312156111cd57600080fd5b86356111d881611135565b955060208701356111e881611135565b9450604087013593506111fd60608801611157565b9250608087013567ffffffffffffffff81111561121957600080fd5b61122589828a0161116b565b979a9699509497509295939492505050565b6000806040838503121561124a57600080fd5b823561125581611135565b9150602083013561126581611135565b809150509250929050565b60008060006060848603121561128557600080fd5b833561129081611135565b925060208401356112a081611135565b929592945050506040919091013590565b600080600080600080600060c0888a0312156112cc57600080fd5b87356112d781611135565b965060208801356112e781611135565b955060408801356112f781611135565b9450606088013561130781611135565b93506080880135925060a088013567ffffffffffffffff81111561132a57600080fd5b6113368a828b0161116b565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561136457600080fd5b873561136f81611135565b9650602088013561137f81611135565b9550604088013561138f81611135565b9450606088013593506113a460808901611157565b925060a088013567ffffffffffffffff81111561132a57600080fd5b6000602082840312156113d257600080fd5b81356113dd81611135565b9392505050565b6000602082840312156113f657600080fd5b81516113dd81611135565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611480606083018486611401565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a08301526114da60c083018486611401565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260006020606081840152845180606085015260005b8181101561153157868101830151858201608001528201611515565b81811115611543576000608083870101525b5063ffffffff9490941660408401525050601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016016080019291505056fea264697066735822122001f259e477011e9a3b3e9ffde836b6b6428967d06f46521c3ba349cab110889464736f6c63430008090033496e697469616c697a61626c653a20636f6e747261637420697320616c726561496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100df5760003560e01c8063761f44931161008c578063c89701a211610066578063c89701a21461021b578063c8b915311461023b578063f2fde38b14610262578063f786becd1461027557600080fd5b8063761f4493146101d75780638da5cb5b146101ea578063aa5574521461020857600080fd5b80635d93a3fc116100bd5780635d93a3fc146101565780636bf2606a1461019a578063715018a6146101cf57600080fd5b80633687011a146100e45780633cb747bf146100f9578063485cc95514610143575b600080fd5b6100f76100f23660046111b4565b61029c565b005b6000546101199073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f7610151366004611237565b610348565b61018a610164366004611270565b606660209081526000938452604080852082529284528284209052825290205460ff1681565b604051901515815260200161013a565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161013a565b6100f7610462565b6100f76101e53660046112b1565b6104ef565b60335473ffffffffffffffffffffffffffffffffffffffff16610119565b6100f7610216366004611349565b61096a565b6065546101199073ffffffffffffffffffffffffffffffffffffffff1681565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b6100f76102703660046113c0565b610983565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b333b15610330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4c314552433732314272696467653a206163636f756e74206973206e6f74206560448201527f787465726e616c6c79206f776e6564000000000000000000000000000000000060648201526084015b60405180910390fd5b6103408686333388888888610acf565b505050505050565b60006103546001610d00565b9050801561039d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b6000805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560658054928516929091169190911790556103fa610ecf565b801561045d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146104e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610327565b6104ed6000610f82565b565b60655473ffffffffffffffffffffffffffffffffffffffff1661052760005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610327565b8073ffffffffffffffffffffffffffffffffffffffff1661061760005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561065c57600080fd5b505afa158015610670573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069491906113e4565b73ffffffffffffffffffffffffffffffffffffffff1614610737576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610327565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152606660209081526040808320938b1683529281528282208783529052205460ff161515600114610806576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f546f6b656e204944206973206e6f7420657363726f77656420696e207468652060448201527f4c312042726964676500000000000000000000000000000000000000000000006064820152608401610327565b73ffffffffffffffffffffffffffffffffffffffff88811660008181526066602090815260408083208c8616845282528083208984529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152918716602483015260448201869052906323b872dd90606401600060405180830381600087803b1580156108c657600080fd5b505af11580156108da573d6000803e3d6000fd5b505050508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac88888888604051610958949392919061144a565b60405180910390a45050505050505050565b61097a8787338888888888610acf565b50505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610a04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610327565b73ffffffffffffffffffffffffffffffffffffffff8116610aa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610327565b610ab081610f82565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600063761f449360e01b888a8989898888604051602401610af6979695949392919061148a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152606686528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610c3657600080fd5b505af1158015610c4a573d6000803e3d6000fd5b5050606554610c73925073ffffffffffffffffffffffffffffffffffffffff1690508583610ff9565b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610ced949392919061144a565b60405180910390a4505050505050505050565b600080547501000000000000000000000000000000000000000000900460ff1615610dcb578160ff166001148015610d375750303b155b610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610327565b506000919050565b60005460ff808416740100000000000000000000000000000000000000009092041610610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610327565b506000805460ff90921674010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055600190565b919050565b6000547501000000000000000000000000000000000000000000900460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610327565b6104ed611081565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b90611053908690859087906004016114e7565b600060405180830381600087803b15801561106d57600080fd5b505af115801561097a573d6000803e3d6000fd5b6000547501000000000000000000000000000000000000000000900460ff1661112c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610327565b6104ed33610f82565b73ffffffffffffffffffffffffffffffffffffffff81168114610ab057600080fd5b803563ffffffff81168114610eca57600080fd5b60008083601f84011261117d57600080fd5b50813567ffffffffffffffff81111561119557600080fd5b6020830191508360208285010111156111ad57600080fd5b9250929050565b60008060008060008060a087890312156111cd57600080fd5b86356111d881611135565b955060208701356111e881611135565b9450604087013593506111fd60608801611157565b9250608087013567ffffffffffffffff81111561121957600080fd5b61122589828a0161116b565b979a9699509497509295939492505050565b6000806040838503121561124a57600080fd5b823561125581611135565b9150602083013561126581611135565b809150509250929050565b60008060006060848603121561128557600080fd5b833561129081611135565b925060208401356112a081611135565b929592945050506040919091013590565b600080600080600080600060c0888a0312156112cc57600080fd5b87356112d781611135565b965060208801356112e781611135565b955060408801356112f781611135565b9450606088013561130781611135565b93506080880135925060a088013567ffffffffffffffff81111561132a57600080fd5b6113368a828b0161116b565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561136457600080fd5b873561136f81611135565b9650602088013561137f81611135565b9550604088013561138f81611135565b9450606088013593506113a460808901611157565b925060a088013567ffffffffffffffff81111561132a57600080fd5b6000602082840312156113d257600080fd5b81356113dd81611135565b9392505050565b6000602082840312156113f657600080fd5b81516113dd81611135565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611480606083018486611401565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a08301526114da60c083018486611401565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260006020606081840152845180606085015260005b8181101561153157868101830151858201608001528201611515565b81811115611543576000608083870101525b5063ffffffff9490941660408401525050601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016016080019291505056fea264697066735822122001f259e477011e9a3b3e9ffde836b6b6428967d06f46521c3ba349cab110889464736f6c63430008090033", - "devdoc": { - "events": { - "ERC721BridgeFinalized(address,address,address,address,uint256,bytes)": { - "params": { - "extraData": "Extra data for use on the client-side.", - "from": "Address that initiated bridging action.", - "localToken": "Address of the token on this domain.", - "remoteToken": "Address of the token on the remote domain.", - "to": "Address to receive the token.", - "tokenId": "ID of the specific token deposited." - } - }, - "ERC721BridgeInitiated(address,address,address,address,uint256,bytes)": { - "params": { - "extraData": "Extra data for use on the client-side.", - "from": "Address that initiated bridging action.", - "localToken": "Address of the token on this domain.", - "remoteToken": "Address of the token on the remote domain.", - "to": "Address to receive the token.", - "tokenId": "ID of the specific token deposited." - } - } - }, - "kind": "dev", - "methods": { - "bridgeERC721(address,address,uint256,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.", - "_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 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.", - "_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.", - "_otherBridge": "Address of the ERC721 bridge on the other 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,address)": { - "params": { - "_messenger": "Address of the CrossDomainMessenger on this network.", - "_otherBridge": "Address of the ERC721 bridge on the other network." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "title": "L1ERC721Bridge", - "version": 1 - }, - "userdoc": { - "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." - } - }, - "kind": "user", - "methods": { - "MAJOR_VERSION()": { - "notice": "Contract version number (major)." - }, - "MINOR_VERSION()": { - "notice": "Contract version number (minor)." - }, - "PATCH_VERSION()": { - "notice": "Contract version number (patch)." - }, - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to the caller's account on L2." - }, - "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to some recipient's account on L2." - }, - "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." - }, - "otherBridge()": { - "notice": "Address of the bridge on the other network." - } - }, - "notice": "The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to make it possible to transfer ERC721 tokens between Optimism and Ethereum. This contract acts as an escrow for ERC721 tokens deposted into L2.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1119, - "contract": "contracts/L1/messaging/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "messenger", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 1361, - "contract": "contracts/L1/messaging/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "_initialized", - "offset": 20, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 1364, - "contract": "contracts/L1/messaging/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "_initializing", - "offset": 21, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 1780, - "contract": "contracts/L1/messaging/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 1241, - "contract": "contracts/L1/messaging/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 1353, - "contract": "contracts/L1/messaging/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 5106, - "contract": "contracts/L1/messaging/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "otherBridge", - "offset": 0, - "slot": "101", - "type": "t_address" - }, - { - "astId": 5115, - "contract": "contracts/L1/messaging/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "deposits", - "offset": 0, - "slot": "102", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "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" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/kovan/L1ERC721BridgeProxy.json b/packages/contracts-periphery/deployments/kovan/L1ERC721BridgeProxy.json deleted file mode 100644 index fab02433d2b4d..0000000000000 --- a/packages/contracts-periphery/deployments/kovan/L1ERC721BridgeProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0x306476D52B5872628B4CD204E9ffFBEfd5ED42B0", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_admin", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "admin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_admin", - "type": "address" - } - ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "implementation", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_implementation", - "type": "address" - } - ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_implementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } - ], - "transactionHash": "0x8525db2ec51afbdfb69020761c677776c0d9cbdd6629285c12bcec1aa4a8f1f5", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5", - "contractAddress": null, - "transactionIndex": 4, - "gasUsed": "502333", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1813a0038fc8d92e0a5054e4be482919e73d6268ff260b59335470ebf5ef198d", - "transactionHash": "0x8525db2ec51afbdfb69020761c677776c0d9cbdd6629285c12bcec1aa4a8f1f5", - "logs": [ - { - "transactionIndex": 4, - "blockNumber": 32196103, - "transactionHash": "0x8525db2ec51afbdfb69020761c677776c0d9cbdd6629285c12bcec1aa4a8f1f5", - "address": "0x306476D52B5872628B4CD204E9ffFBEfd5ED42B0", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58", - "logIndex": 1, - "blockHash": "0x1813a0038fc8d92e0a5054e4be482919e73d6268ff260b59335470ebf5ef198d" - } - ], - "blockNumber": 32196103, - "cumulativeGasUsed": "625043", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "9bf33bb642648b258386a9c465b5d346", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"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\"}}},\"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 owner. The owner has the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"The address of the implementation contract\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"The calldata to delegatecall the new implementation with\",\"_implementation\":\"The address of the implementation contract\"}}},\"title\":\"Proxy\",\"version\":1},\"userdoc\":{\"events\":{\"AdminChanged(address,address)\":{\"notice\":\"An event that is emitted each time the owner is upgraded. This event is part of the EIP 1967 spec.\"},\"Upgraded(address)\":{\"notice\":\"An event that is emitted each time the implementation is changed. This event is part of the EIP 1967 spec.\"}},\"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\":\"set the initial owner during contract deployment. The owner is stored at the eip1967 owner storage slot so that storage collision with the implementation is not possible.\"},\"implementation()\":{\"notice\":\"Queries the implementation address.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at this address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. This is useful to ensure atomic `initialize()` based upgrades.\"}},\"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 offchain simulation.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Proxy\\n * @notice Proxy is a transparent proxy that passes through the call\\n * if the caller is the owner or if the caller is `address(0)`,\\n * meaning that the call originated from an offchain simulation.\\n */\\ncontract Proxy {\\n /**\\n * @notice An event that is emitted each time the implementation is changed.\\n * This event is part of the EIP 1967 spec.\\n *\\n * @param implementation The address of the implementation contract\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @notice An event that is emitted each time the owner is upgraded.\\n * This event is part of the EIP 1967 spec.\\n *\\n * @param previousAdmin The previous owner of the contract\\n * @param newAdmin The new owner of the contract\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @notice The storage slot that holds the address of the implementation.\\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n */\\n bytes32 internal constant IMPLEMENTATION_KEY =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @notice The storage slot that holds the address of the owner.\\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n */\\n bytes32 internal constant OWNER_KEY =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @notice set the initial owner during contract deployment. The\\n * owner is stored at the eip1967 owner storage slot so that\\n * storage collision with the implementation is not possible.\\n *\\n * @param _admin Address of the initial contract owner. The owner has\\n * the ability to access the transparent proxy interface.\\n */\\n constructor(address _admin) {\\n _changeAdmin(_admin);\\n }\\n\\n // slither-disable-next-line locked-ether\\n fallback() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n /**\\n * @notice A modifier that reverts if not called by the owner\\n * or by `address(0)` to allow `eth_call` to interact\\n * with the proxy without needing to use low level storage\\n * inspection. It is assumed that nobody controls the private\\n * key for `address(0)`.\\n */\\n modifier proxyCallIfNotAdmin() {\\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\\n _;\\n } else {\\n // This WILL halt the call frame on completion.\\n _doProxyCall();\\n }\\n }\\n\\n /**\\n * @notice Set the implementation contract address. The code at this\\n * address will execute when this contract is called.\\n *\\n * @param _implementation The address of the implementation contract\\n */\\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\\n _setImplementation(_implementation);\\n }\\n\\n /**\\n * @notice Set the implementation and call a function in a single\\n * transaction. This is useful to ensure atomic `initialize()`\\n * based upgrades.\\n *\\n * @param _implementation The address of the implementation contract\\n * @param _data The calldata to delegatecall the new\\n * implementation with\\n */\\n function upgradeToAndCall(address _implementation, bytes calldata _data)\\n external\\n payable\\n proxyCallIfNotAdmin\\n returns (bytes memory)\\n {\\n _setImplementation(_implementation);\\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\\n require(success);\\n return returndata;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\\n _changeAdmin(_admin);\\n }\\n\\n /**\\n * @notice Gets the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function admin() external proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() external proxyCallIfNotAdmin returns (address) {\\n return _getImplementation();\\n }\\n\\n /**\\n * @notice Sets the implementation address.\\n *\\n * @param _implementation New implementation address.\\n */\\n function _setImplementation(address _implementation) internal {\\n assembly {\\n sstore(IMPLEMENTATION_KEY, _implementation)\\n }\\n emit Upgraded(_implementation);\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n address implementation;\\n assembly {\\n implementation := sload(IMPLEMENTATION_KEY)\\n }\\n return implementation;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function _changeAdmin(address _admin) internal {\\n address previous = _getAdmin();\\n assembly {\\n sstore(OWNER_KEY, _admin)\\n }\\n emit AdminChanged(previous, _admin);\\n }\\n\\n /**\\n * @notice Queries the owner of the proxy contract.\\n *\\n * @return owner address.\\n */\\n function _getAdmin() internal view returns (address) {\\n address owner;\\n assembly {\\n owner := sload(OWNER_KEY)\\n }\\n return owner;\\n }\\n\\n /**\\n * @notice Performs the proxy call via a delegatecall.\\n */\\n function _doProxyCall() internal {\\n address implementation = _getImplementation();\\n\\n require(implementation != address(0), \\\"Proxy: implementation not initialized\\\");\\n\\n assembly {\\n // Copy calldata into memory at 0x0....calldatasize.\\n calldatacopy(0x0, 0x0, calldatasize())\\n\\n // Perform the delegatecall, make sure to pass all available gas.\\n let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)\\n\\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\\n // overwrite the calldata that we just copied into memory but that doesn't really\\n // matter because we'll be returning in a second anyway.\\n returndatacopy(0x0, 0x0, returndatasize())\\n\\n // Success == 0 means a revert. We'll revert too and pass the data up.\\n if iszero(success) {\\n revert(0x0, returndatasize())\\n }\\n\\n // Otherwise we'll just return and pass the data up.\\n return(0x0, returndatasize())\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2a6719fd9a11adf0efba0243e5c68d56b255296b84cc82bd39326c902e055077\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506040516108ac3803806108ac83398101604081905261002f916100b2565b6100388161003e565b506100e2565b600061005660008051602061088c8339815191525490565b60008051602061088c833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b61079b806100f16000396000f3fe60806040526004361061005a5760003560e01c80635c60da1b116100435780635c60da1b146100ad5780638f283970146100e7578063f851a440146101075761005a565b80633659cfe6146100645780634f1ef28614610084575b61006261011c565b005b34801561007057600080fd5b5061006261007f366004610644565b610212565b61009761009236600461065f565b610284565b6040516100a491906106e2565b60405180910390f35b3480156100b957600080fd5b506100c2610384565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a4565b3480156100f357600080fd5b50610062610102366004610644565b61041b565b34801561011357600080fd5b506100c2610482565b60006101467f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166101ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a6564000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b3660008037600080366000845af43d6000803e8061020c573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061026b575033155b1561027c576102798161050e565b50565b61027961011c565b60606102ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102e5575033155b15610375576102f38461050e565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161031d929190610755565b600060405180830381855af49150503d8060008114610358576040519150601f19603f3d011682016040523d82523d6000602084013e61035d565b606091505b50915091508161036c57600080fd5b915061037d9050565b61037d61011c565b9392505050565b60006103ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103e5575033155b1561041057507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b61041861011c565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610474575033155b1561027c5761027981610576565b60006104ac7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104e3575033155b1561041057507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006105a07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461063f57600080fd5b919050565b60006020828403121561065657600080fd5b61037d8261061b565b60008060006040848603121561067457600080fd5b61067d8461061b565b9250602084013567ffffffffffffffff8082111561069a57600080fd5b818601915086601f8301126106ae57600080fd5b8135818111156106bd57600080fd5b8760208285010111156106cf57600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b8181101561070f578581018301518582016040015282016106f3565b81811115610721576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea264697066735822122002cf23bcc281eec5c701686c2374a3972d766187632ccdd7ca1fe3d13cb4866264736f6c63430008090033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005a5760003560e01c80635c60da1b116100435780635c60da1b146100ad5780638f283970146100e7578063f851a440146101075761005a565b80633659cfe6146100645780634f1ef28614610084575b61006261011c565b005b34801561007057600080fd5b5061006261007f366004610644565b610212565b61009761009236600461065f565b610284565b6040516100a491906106e2565b60405180910390f35b3480156100b957600080fd5b506100c2610384565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a4565b3480156100f357600080fd5b50610062610102366004610644565b61041b565b34801561011357600080fd5b506100c2610482565b60006101467f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166101ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a6564000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b3660008037600080366000845af43d6000803e8061020c573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061026b575033155b1561027c576102798161050e565b50565b61027961011c565b60606102ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102e5575033155b15610375576102f38461050e565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161031d929190610755565b600060405180830381855af49150503d8060008114610358576040519150601f19603f3d011682016040523d82523d6000602084013e61035d565b606091505b50915091508161036c57600080fd5b915061037d9050565b61037d61011c565b9392505050565b60006103ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103e5575033155b1561041057507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b61041861011c565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610474575033155b1561027c5761027981610576565b60006104ac7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104e3575033155b1561041057507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006105a07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461063f57600080fd5b919050565b60006020828403121561065657600080fd5b61037d8261061b565b60008060006040848603121561067457600080fd5b61067d8461061b565b9250602084013567ffffffffffffffff8082111561069a57600080fd5b818601915086601f8301126106ae57600080fd5b8135818111156106bd57600080fd5b8760208285010111156106cf57600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b8181101561070f578581018301518582016040015282016106f3565b81811115610721576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea264697066735822122002cf23bcc281eec5c701686c2374a3972d766187632ccdd7ca1fe3d13cb4866264736f6c63430008090033", - "devdoc": { - "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" - } - } - }, - "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 owner. The owner has the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "The address of the implementation contract" - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "The calldata to delegatecall the new implementation with", - "_implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy", - "version": 1 - }, - "userdoc": { - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP 1967 spec." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP 1967 spec." - } - }, - "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": "set the initial owner during contract deployment. The owner is stored at the eip1967 owner storage slot so that storage collision with the implementation is not possible." - }, - "implementation()": { - "notice": "Queries the implementation address." - }, - "upgradeTo(address)": { - "notice": "Set the implementation contract address. The code at this address will execute when this contract is called." - }, - "upgradeToAndCall(address,bytes)": { - "notice": "Set the implementation and call a function in a single transaction. This is useful to ensure atomic `initialize()` based upgrades." - } - }, - "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 offchain simulation.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-goerli/L2ERC721Bridge.json b/packages/contracts-periphery/deployments/optimism-goerli/L2ERC721Bridge.json new file mode 100644 index 0000000000000..8490bc031bbd9 --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism-goerli/L2ERC721Bridge.json @@ -0,0 +1,386 @@ +{ + "address": "0x2fBFa09Db7f33b7a8fBCEEf80C75DA48E6B8c550", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_messenger", + "type": "address" + }, + { + "internalType": "address", + "name": "_otherBridge", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC721BridgeFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC721BridgeInitiated", + "type": "event" + }, + { + "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" + } + ], + "name": "bridgeERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "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" + } + ], + "name": "bridgeERC721To", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "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" + } + ], + "name": "finalizeBridgeERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "messenger", + "outputs": [ + { + "internalType": "contract CrossDomainMessenger", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "otherBridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x8363e49e509912bacb8b74e676cc4d1f7470c2ed9df31b93ccf4cb951bfec27a", + "receipt": { + "to": null, + "from": "0x5c679a57e018F5F146838138d3E032Ef4913D551", + "contractAddress": "0x2fBFa09Db7f33b7a8fBCEEf80C75DA48E6B8c550", + "transactionIndex": 0, + "gasUsed": "1344187", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5aaf338316da4a5490579ef2d262419e00fc47635c18308f7491535236e31650", + "transactionHash": "0x8363e49e509912bacb8b74e676cc4d1f7470c2ed9df31b93ccf4cb951bfec27a", + "logs": [], + "blockNumber": 1562997, + "cumulativeGasUsed": "1344187", + "status": 1, + "byzantium": true + }, + "args": [ + "0x4200000000000000000000000000000000000007", + "0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9" + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeInitiated\",\"type\":\"event\"},{\"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\"}],\"name\":\"bridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}],\"name\":\"bridgeERC721To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}],\"name\":\"finalizeBridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"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\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\",\"_otherBridge\":\"Address of the ERC721 bridge on the other network.\"}},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to L1. Data supplied here will not be used to execute any code on L1 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.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"L2ERC721Bridge\",\"version\":1},\"userdoc\":{\"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.\"}},\"kind\":\"user\",\"methods\":{\"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.\"},\"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.\"},\"messenger()\":{\"notice\":\"Messenger contract on this domain.\"},\"otherBridge()\":{\"notice\":\"Address of the bridge on the other network.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge. This contract also acts as a burner for tokens being withdrawn. **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.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/L2ERC721Bridge.sol\":\"L2ERC721Bridge\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { Types } from \\\"./Types.sol\\\";\\nimport { Hashing } from \\\"./Hashing.sol\\\";\\nimport { RLPWriter } from \\\"./rlp/RLPWriter.sol\\\";\\n\\n/**\\n * @title Encoding\\n * @notice Encoding handles Optimism's various different encoding schemes.\\n */\\nlibrary Encoding {\\n /**\\n * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\\n * to the L2 system. Useful for searching for a deposit in the L2 system. The\\n * transaction is prefixed with 0x7e to identify its EIP-2718 type.\\n *\\n * @param _tx User deposit transaction to encode.\\n *\\n * @return RLP encoded L2 deposit transaction.\\n */\\n function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\\n internal\\n pure\\n returns (bytes memory)\\n {\\n bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\\n bytes[] memory raw = new bytes[](8);\\n raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\\n raw[1] = RLPWriter.writeAddress(_tx.from);\\n raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\\\"\\\") : RLPWriter.writeAddress(_tx.to);\\n raw[3] = RLPWriter.writeUint(_tx.mint);\\n raw[4] = RLPWriter.writeUint(_tx.value);\\n raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\\n raw[6] = RLPWriter.writeBool(false);\\n raw[7] = RLPWriter.writeBytes(_tx.data);\\n return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\\n }\\n\\n /**\\n * @notice Encodes the cross domain message based on the version that is encoded into the\\n * message nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes memory) {\\n (, uint16 version) = decodeVersionedNonce(_nonce);\\n if (version == 0) {\\n return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\\n } else if (version == 1) {\\n return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\\n } else {\\n revert(\\\"Encoding: unknown cross domain message version\\\");\\n }\\n }\\n\\n /**\\n * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\\n *\\n * @param _target Address of the target of the message.\\n * @param _sender Address of the sender of the message.\\n * @param _data Data to send with the message.\\n * @param _nonce Message nonce.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessageV0(\\n address _target,\\n address _sender,\\n bytes memory _data,\\n uint256 _nonce\\n ) internal pure returns (bytes memory) {\\n return\\n abi.encodeWithSignature(\\n \\\"relayMessage(address,address,bytes,uint256)\\\",\\n _target,\\n _sender,\\n _data,\\n _nonce\\n );\\n }\\n\\n /**\\n * @notice Encodes a cross domain message based on the V1 (current) encoding.\\n *\\n * @param _nonce Message nonce.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessageV1(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes memory) {\\n return\\n abi.encodeWithSignature(\\n \\\"relayMessage(uint256,address,address,uint256,uint256,bytes)\\\",\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _gasLimit,\\n _data\\n );\\n }\\n\\n /**\\n * @notice Adds a version number into the first two bytes of a message nonce.\\n *\\n * @param _nonce Message nonce to encode into.\\n * @param _version Version number to encode into the message nonce.\\n *\\n * @return Message nonce with version encoded into the first two bytes.\\n */\\n function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\\n uint256 nonce;\\n assembly {\\n nonce := or(shl(240, _version), _nonce)\\n }\\n return nonce;\\n }\\n\\n /**\\n * @notice Pulls the version out of a version-encoded nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n *\\n * @return Nonce without encoded version.\\n * @return Version of the message.\\n */\\n function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\\n uint240 nonce;\\n uint16 version;\\n assembly {\\n nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\\n version := shr(240, _nonce)\\n }\\n return (nonce, version);\\n }\\n}\\n\",\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { Types } from \\\"./Types.sol\\\";\\nimport { Encoding } from \\\"./Encoding.sol\\\";\\n\\n/**\\n * @title Hashing\\n * @notice Hashing handles Optimism's various different hashing schemes.\\n */\\nlibrary Hashing {\\n /**\\n * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\\n * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\\n * system.\\n *\\n * @param _tx User deposit transaction to hash.\\n *\\n * @return Hash of the RLP encoded L2 deposit transaction.\\n */\\n function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return keccak256(Encoding.encodeDepositTransaction(_tx));\\n }\\n\\n /**\\n * @notice Computes the deposit transaction's \\\"source hash\\\", a value that guarantees the hash\\n * of the L2 transaction that corresponds to a deposit is unique and is\\n * deterministically generated from L1 transaction data.\\n *\\n * @param _l1BlockHash Hash of the L1 block where the deposit was included.\\n * @param _logIndex The index of the log that created the deposit transaction.\\n *\\n * @return Hash of the deposit transaction's \\\"source hash\\\".\\n */\\n function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\\n internal\\n pure\\n returns (bytes32)\\n {\\n bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\\n return keccak256(abi.encode(bytes32(0), depositId));\\n }\\n\\n /**\\n * @notice Hashes the cross domain message based on the version that is encoded into the\\n * message nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes32) {\\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\\n if (version == 0) {\\n return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\\n } else if (version == 1) {\\n return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\\n } else {\\n revert(\\\"Hashing: unknown cross domain message version\\\");\\n }\\n }\\n\\n /**\\n * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\\n *\\n * @param _target Address of the target of the message.\\n * @param _sender Address of the sender of the message.\\n * @param _data Data to send with the message.\\n * @param _nonce Message nonce.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessageV0(\\n address _target,\\n address _sender,\\n bytes memory _data,\\n uint256 _nonce\\n ) internal pure returns (bytes32) {\\n return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\\n }\\n\\n /**\\n * @notice Hashes a cross domain message based on the V1 (current) encoding.\\n *\\n * @param _nonce Message nonce.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessageV1(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes32) {\\n return\\n keccak256(\\n Encoding.encodeCrossDomainMessageV1(\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _gasLimit,\\n _data\\n )\\n );\\n }\\n\\n /**\\n * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\\n *\\n * @param _tx Withdrawal transaction to hash.\\n *\\n * @return Hashed withdrawal transaction.\\n */\\n function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\\n );\\n }\\n\\n /**\\n * @notice Hashes the various elements of an output root proof into an output root hash which\\n * can be used to check if the proof is valid.\\n *\\n * @param _outputRootProof Output root proof which should hash to an output root.\\n *\\n * @return Hashed output root proof.\\n */\\n function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encode(\\n _outputRootProof.version,\\n _outputRootProof.stateRoot,\\n _outputRootProof.messagePasserStorageRoot,\\n _outputRootProof.latestBlockhash\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title SafeCall\\n * @notice Perform low level safe calls\\n */\\nlibrary SafeCall {\\n /**\\n * @notice Perform a low level call without copying any returndata\\n *\\n * @param _target Address to call\\n * @param _gas Amount of gas to pass to the call\\n * @param _value Amount of value to pass to the call\\n * @param _calldata Calldata to pass to the call\\n */\\n function call(\\n address _target,\\n uint256 _gas,\\n uint256 _value,\\n bytes memory _calldata\\n ) internal returns (bool) {\\n bool _success;\\n assembly {\\n _success := call(\\n _gas, // gas\\n _target, // recipient\\n _value, // ether value\\n add(_calldata, 0x20), // inloc\\n mload(_calldata), // inlen\\n 0, // outloc\\n 0 // outlen\\n )\\n }\\n return _success;\\n }\\n}\\n\",\"keccak256\":\"0xbb0621c028c18e9d5a54cf1a8136cf2e77f161de48aeb8d911e230f6b280c9ed\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Types\\n * @notice Contains various types used throughout the Optimism contract system.\\n */\\nlibrary Types {\\n /**\\n * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\\n * timestamp that the output root is posted. This timestamp is used to verify that the\\n * finalization period has passed since the output root was submitted.\\n */\\n struct OutputProposal {\\n bytes32 outputRoot;\\n uint256 timestamp;\\n }\\n\\n /**\\n * @notice Struct representing the elements that are hashed together to generate an output root\\n * which itself represents a snapshot of the L2 state.\\n */\\n struct OutputRootProof {\\n bytes32 version;\\n bytes32 stateRoot;\\n bytes32 messagePasserStorageRoot;\\n bytes32 latestBlockhash;\\n }\\n\\n /**\\n * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\\n * user (as opposed to a system deposit transaction generated by the system).\\n */\\n struct UserDepositTransaction {\\n address from;\\n address to;\\n bool isCreation;\\n uint256 value;\\n uint256 mint;\\n uint64 gasLimit;\\n bytes data;\\n bytes32 l1BlockHash;\\n uint256 logIndex;\\n }\\n\\n /**\\n * @notice Struct representing a withdrawal transaction.\\n */\\n struct WithdrawalTransaction {\\n uint256 nonce;\\n address sender;\\n address target;\\n uint256 value;\\n uint256 gasLimit;\\n bytes data;\\n }\\n}\\n\",\"keccak256\":\"0x69ca98e57a7cbe60cffeb0f76f6f9279010941b1931581e9a35478f30e2546d1\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\\n * @title RLPWriter\\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\\n * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\\n * modifications to improve legibility.\\n */\\nlibrary RLPWriter {\\n /**\\n * @notice RLP encodes a byte string.\\n *\\n * @param _in The byte string to encode.\\n *\\n * @return The RLP encoded string in bytes.\\n */\\n function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\\n bytes memory encoded;\\n\\n if (_in.length == 1 && uint8(_in[0]) < 128) {\\n encoded = _in;\\n } else {\\n encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\\n }\\n\\n return encoded;\\n }\\n\\n /**\\n * @notice RLP encodes a list of RLP encoded byte byte strings.\\n *\\n * @param _in The list of RLP encoded byte strings.\\n *\\n * @return The RLP encoded list of items in bytes.\\n */\\n function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\\n bytes memory list = _flatten(_in);\\n return abi.encodePacked(_writeLength(list.length, 192), list);\\n }\\n\\n /**\\n * @notice RLP encodes a string.\\n *\\n * @param _in The string to encode.\\n *\\n * @return The RLP encoded string in bytes.\\n */\\n function writeString(string memory _in) internal pure returns (bytes memory) {\\n return writeBytes(bytes(_in));\\n }\\n\\n /**\\n * @notice RLP encodes an address.\\n *\\n * @param _in The address to encode.\\n *\\n * @return The RLP encoded address in bytes.\\n */\\n function writeAddress(address _in) internal pure returns (bytes memory) {\\n return writeBytes(abi.encodePacked(_in));\\n }\\n\\n /**\\n * @notice RLP encodes a uint.\\n *\\n * @param _in The uint256 to encode.\\n *\\n * @return The RLP encoded uint256 in bytes.\\n */\\n function writeUint(uint256 _in) internal pure returns (bytes memory) {\\n return writeBytes(_toBinary(_in));\\n }\\n\\n /**\\n * @notice RLP encodes a bool.\\n *\\n * @param _in The bool to encode.\\n *\\n * @return The RLP encoded bool in bytes.\\n */\\n function writeBool(bool _in) internal pure returns (bytes memory) {\\n bytes memory encoded = new bytes(1);\\n encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\\n return encoded;\\n }\\n\\n /**\\n * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\\n *\\n * @param _len The length of the string or the payload.\\n * @param _offset 128 if item is string, 192 if item is list.\\n *\\n * @return RLP encoded bytes.\\n */\\n function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\\n bytes memory encoded;\\n\\n if (_len < 56) {\\n encoded = new bytes(1);\\n encoded[0] = bytes1(uint8(_len) + uint8(_offset));\\n } else {\\n uint256 lenLen;\\n uint256 i = 1;\\n while (_len / i != 0) {\\n lenLen++;\\n i *= 256;\\n }\\n\\n encoded = new bytes(lenLen + 1);\\n encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\\n for (i = 1; i <= lenLen; i++) {\\n encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\\n }\\n }\\n\\n return encoded;\\n }\\n\\n /**\\n * @notice Encode integer in big endian binary form with no leading zeroes.\\n *\\n * @param _x The integer to encode.\\n *\\n * @return RLP encoded bytes.\\n */\\n function _toBinary(uint256 _x) private pure returns (bytes memory) {\\n bytes memory b = abi.encodePacked(_x);\\n\\n uint256 i = 0;\\n for (; i < 32; i++) {\\n if (b[i] != 0) {\\n break;\\n }\\n }\\n\\n bytes memory res = new bytes(32 - i);\\n for (uint256 j = 0; j < res.length; j++) {\\n res[j] = b[i++];\\n }\\n\\n return res;\\n }\\n\\n /**\\n * @custom:attribution https://github.com/Arachnid/solidity-stringutils\\n * @notice Copies a piece of memory to another location.\\n *\\n * @param _dest Destination location.\\n * @param _src Source location.\\n * @param _len Length of memory to copy.\\n */\\n function _memcpy(\\n uint256 _dest,\\n uint256 _src,\\n uint256 _len\\n ) private pure {\\n uint256 dest = _dest;\\n uint256 src = _src;\\n uint256 len = _len;\\n\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n uint256 mask;\\n unchecked {\\n mask = 256**(32 - len) - 1;\\n }\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n\\n /**\\n * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\\n * @notice Flattens a list of byte strings into one byte string.\\n *\\n * @param _list List of byte strings to flatten.\\n *\\n * @return The flattened byte string.\\n */\\n function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\\n if (_list.length == 0) {\\n return new bytes(0);\\n }\\n\\n uint256 len;\\n uint256 i = 0;\\n for (; i < _list.length; i++) {\\n len += _list[i].length;\\n }\\n\\n bytes memory flattened = new bytes(len);\\n uint256 flattenedPtr;\\n assembly {\\n flattenedPtr := add(flattened, 0x20)\\n }\\n\\n for (i = 0; i < _list.length; i++) {\\n bytes memory item = _list[i];\\n\\n uint256 listPtr;\\n assembly {\\n listPtr := add(item, 0x20)\\n }\\n\\n _memcpy(flattenedPtr, listPtr, item.length);\\n flattenedPtr += _list[i].length;\\n }\\n\\n return flattened;\\n }\\n}\\n\",\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {\\n PausableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {\\n ReentrancyGuardUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeCall } from \\\"../libraries/SafeCall.sol\\\";\\nimport { Hashing } from \\\"../libraries/Hashing.sol\\\";\\nimport { Encoding } from \\\"../libraries/Encoding.sol\\\";\\n\\n/**\\n * @custom:legacy\\n * @title CrossDomainMessengerLegacySpacer\\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\\n * libAddressManager variable used to exist. Must be the first contract in the inheritance\\n * tree of the CrossDomainMessenger\\n */\\ncontract CrossDomainMessengerLegacySpacer {\\n /**\\n * @custom:legacy\\n * @custom:spacer libAddressManager\\n * @notice Spacer for backwards compatibility.\\n */\\n address private spacer_0_0_20;\\n}\\n\\n/**\\n * @custom:upgradeable\\n * @title CrossDomainMessenger\\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\\n * cross-chain messenger contracts. It's designed to be a universal interface that only\\n * needs to be extended slightly to provide low-level message passing functionality on each\\n * chain it's deployed on. Currently only designed for message passing between two paired\\n * chains and does not support one-to-many interactions.\\n */\\nabstract contract CrossDomainMessenger is\\n CrossDomainMessengerLegacySpacer,\\n OwnableUpgradeable,\\n PausableUpgradeable,\\n ReentrancyGuardUpgradeable\\n{\\n /**\\n * @notice Current message version identifier.\\n */\\n uint16 public constant MESSAGE_VERSION = 1;\\n\\n /**\\n * @notice Constant overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\\n\\n /**\\n * @notice Numerator for dynamic overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\\n\\n /**\\n * @notice Denominator for dynamic overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\\n\\n /**\\n * @notice Extra gas added to base gas for each byte of calldata in a message.\\n */\\n uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\\n\\n /**\\n * @notice Minimum amount of gas required to relay a message.\\n */\\n uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\\n\\n /**\\n * @notice Amount of gas held in reserve to guarantee that relay execution completes.\\n */\\n uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\\n\\n /**\\n * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\\n * because performing an SSTORE on a non-zero value is significantly cheaper than on a\\n * zero value.\\n */\\n address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\\n\\n /**\\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\\n */\\n address public immutable otherMessenger;\\n\\n /**\\n * @custom:legacy\\n * @custom:spacer blockedMessages\\n * @notice Spacer for backwards compatibility.\\n */\\n mapping(bytes32 => bool) private spacer_201_0_32;\\n\\n /**\\n * @custom:legacy\\n * @custom:spacer relayedMessages\\n * @notice Spacer for backwards compatibility.\\n */\\n mapping(bytes32 => bool) private spacer_202_0_32;\\n\\n /**\\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\\n * be present in this mapping if it has successfully been relayed on this chain, and\\n * can therefore not be relayed again.\\n */\\n mapping(bytes32 => bool) public successfulMessages;\\n\\n /**\\n * @notice Address of the sender of the currently executing message on the other chain. If the\\n * value of this variable is the default value (0x00000000...dead) then no message is\\n * currently being executed. Use the xDomainMessageSender getter which will throw an\\n * error if this is the case.\\n */\\n address internal xDomainMsgSender;\\n\\n /**\\n * @notice Nonce for the next message to be sent, without the message version applied. Use the\\n * messageNonce getter which will insert the message version into the nonce to give you\\n * the actual nonce to be used for the message.\\n */\\n uint240 internal msgNonce;\\n\\n /**\\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\\n * be present in this mapping if it failed to be relayed on this chain at least once.\\n * If a message is successfully relayed on the first attempt, then it will only be\\n * present within the successfulMessages mapping.\\n */\\n mapping(bytes32 => bool) public receivedMessages;\\n\\n /**\\n * @notice Reserve extra slots in the storage layout for future upgrades.\\n * A gap size of 41 was chosen here, so that the first slot used in a child contract\\n * would be a multiple of 50.\\n */\\n uint256[42] private __gap;\\n\\n /**\\n * @notice Emitted whenever a message is sent to the other chain.\\n *\\n * @param target Address of the recipient of the message.\\n * @param sender Address of the sender of the message.\\n * @param message Message to trigger the recipient address with.\\n * @param messageNonce Unique nonce attached to the message.\\n * @param gasLimit Minimum gas limit that the message can be executed with.\\n */\\n event SentMessage(\\n address indexed target,\\n address sender,\\n bytes message,\\n uint256 messageNonce,\\n uint256 gasLimit\\n );\\n\\n /**\\n * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\\n * SentMessage event without breaking the ABI of this contract, this is good enough.\\n *\\n * @param sender Address of the sender of the message.\\n * @param value ETH value sent along with the message to the recipient.\\n */\\n event SentMessageExtension1(address indexed sender, uint256 value);\\n\\n /**\\n * @notice Emitted whenever a message is successfully relayed on this chain.\\n *\\n * @param msgHash Hash of the message that was relayed.\\n */\\n event RelayedMessage(bytes32 indexed msgHash);\\n\\n /**\\n * @notice Emitted whenever a message fails to be relayed on this chain.\\n *\\n * @param msgHash Hash of the message that failed to be relayed.\\n */\\n event FailedRelayedMessage(bytes32 indexed msgHash);\\n\\n /**\\n * @param _otherMessenger Address of the messenger on the paired chain.\\n */\\n constructor(address _otherMessenger) {\\n otherMessenger = _otherMessenger;\\n }\\n\\n /**\\n * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\\n * security mechanism just in case. Owner should be the same as the upgrade wallet to\\n * maintain the security model of the system as a whole.\\n */\\n function pause() external onlyOwner {\\n _pause();\\n }\\n\\n /**\\n * @notice Allows the owner of this contract to resume message relaying once paused.\\n */\\n function unpause() external onlyOwner {\\n _unpause();\\n }\\n\\n /**\\n * @notice Sends a message to some target address on the other chain. Note that if the call\\n * always reverts, then the message will be unrelayable, and any ETH sent will be\\n * permanently locked. The same will occur if the target on the other chain is\\n * considered unsafe (see the _isUnsafeTarget() function).\\n *\\n * @param _target Target contract or wallet address.\\n * @param _message Message to trigger the target address with.\\n * @param _minGasLimit Minimum gas limit that the message can be executed with.\\n */\\n function sendMessage(\\n address _target,\\n bytes calldata _message,\\n uint32 _minGasLimit\\n ) external payable {\\n // Triggers a message to the other messenger. Note that the amount of gas provided to the\\n // message is the amount of gas requested by the user PLUS the base gas value. We want to\\n // guarantee the property that the call to the target contract will always have at least\\n // the minimum gas limit specified by the user.\\n _sendMessage(\\n otherMessenger,\\n baseGas(_message, _minGasLimit),\\n msg.value,\\n abi.encodeWithSelector(\\n this.relayMessage.selector,\\n messageNonce(),\\n msg.sender,\\n _target,\\n msg.value,\\n _minGasLimit,\\n _message\\n )\\n );\\n\\n emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\\n emit SentMessageExtension1(msg.sender, msg.value);\\n\\n unchecked {\\n ++msgNonce;\\n }\\n }\\n\\n /**\\n * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\\n * be executed via cross-chain call from the other messenger OR if the message was\\n * already received once and is currently being replayed.\\n *\\n * @param _nonce Nonce of the message being relayed.\\n * @param _sender Address of the user who sent the message.\\n * @param _target Address that the message is targeted at.\\n * @param _value ETH value to send with the message.\\n * @param _minGasLimit Minimum amount of gas that the message can be executed with.\\n * @param _message Message to send to the target.\\n */\\n function relayMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _minGasLimit,\\n bytes calldata _message\\n ) external payable nonReentrant whenNotPaused {\\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\\n\\n // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\\n // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\\n // to the value or minGasLimit fields, which can create unexpected issues for end-users.\\n require(\\n version == 1,\\n \\\"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\\\"\\n );\\n\\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _minGasLimit,\\n _message\\n );\\n\\n if (_isOtherMessenger()) {\\n // This property should always hold when the message is first submitted (as opposed to\\n // being replayed).\\n assert(msg.value == _value);\\n } else {\\n require(\\n msg.value == 0,\\n \\\"CrossDomainMessenger: value must be zero unless message is from a system address\\\"\\n );\\n\\n require(\\n receivedMessages[versionedHash],\\n \\\"CrossDomainMessenger: message cannot be replayed\\\"\\n );\\n }\\n\\n require(\\n _isUnsafeTarget(_target) == false,\\n \\\"CrossDomainMessenger: cannot send message to blocked system address\\\"\\n );\\n\\n require(\\n successfulMessages[versionedHash] == false,\\n \\\"CrossDomainMessenger: message has already been relayed\\\"\\n );\\n\\n require(\\n gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\\n \\\"CrossDomainMessenger: insufficient gas to relay message\\\"\\n );\\n\\n xDomainMsgSender = _sender;\\n bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\\n\\n if (success == true) {\\n successfulMessages[versionedHash] = true;\\n emit RelayedMessage(versionedHash);\\n } else {\\n receivedMessages[versionedHash] = true;\\n emit FailedRelayedMessage(versionedHash);\\n }\\n }\\n\\n /**\\n * @notice Retrieves the address of the contract or wallet that initiated the currently\\n * executing message on the other chain. Will throw an error if there is no message\\n * currently being executed. Allows the recipient of a call to see who triggered it.\\n *\\n * @return Address of the sender of the currently executing message on the other chain.\\n */\\n function xDomainMessageSender() external view returns (address) {\\n require(\\n xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\\n \\\"CrossDomainMessenger: xDomainMessageSender is not set\\\"\\n );\\n\\n return xDomainMsgSender;\\n }\\n\\n /**\\n * @notice Retrieves the next message nonce. Message version will be added to the upper two\\n * bytes of the message nonce. Message version allows us to treat messages as having\\n * different structures.\\n *\\n * @return Nonce of the next message to be sent, with added message version.\\n */\\n function messageNonce() public view returns (uint256) {\\n return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\\n }\\n\\n /**\\n * @notice Computes the amount of gas required to guarantee that a given message will be\\n * received on the other chain without running out of gas. Guaranteeing that a message\\n * will not run out of gas is important because this ensures that a message can always\\n * be replayed on the other chain if it fails to execute completely.\\n *\\n * @param _message Message to compute the amount of required gas for.\\n * @param _minGasLimit Minimum desired gas limit when message goes to target.\\n *\\n * @return Amount of gas required to guarantee message receipt.\\n */\\n function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\\n return\\n // Dynamic overhead\\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\\n // Calldata overhead\\n (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\\n // Constant overhead\\n MIN_GAS_CONSTANT_OVERHEAD;\\n }\\n\\n /**\\n * @notice Intializer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function __CrossDomainMessenger_init() internal onlyInitializing {\\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\\n __Context_init_unchained();\\n __Ownable_init_unchained();\\n __Pausable_init_unchained();\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n /**\\n * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\\n * contracts because the logic for this depends on the network where the messenger is\\n * being deployed.\\n *\\n * @param _to Recipient of the message on the other chain.\\n * @param _gasLimit Minimum gas limit the message can be executed with.\\n * @param _value Amount of ETH to send with the message.\\n * @param _data Message data.\\n */\\n function _sendMessage(\\n address _to,\\n uint64 _gasLimit,\\n uint256 _value,\\n bytes memory _data\\n ) internal virtual;\\n\\n /**\\n * @notice Checks whether the message is coming from the other messenger. Implemented by child\\n * contracts because the logic for this depends on the network where the messenger is\\n * being deployed.\\n *\\n * @return Whether the message is coming from the other messenger.\\n */\\n function _isOtherMessenger() internal view virtual returns (bool);\\n\\n /**\\n * @notice Checks whether a given call target is a system address that could cause the\\n * messenger to peform an unsafe action. This is NOT a mechanism for blocking user\\n * addresses. This is ONLY used to prevent the execution of messages to specific\\n * system addresses that could cause security issues, e.g., having the\\n * CrossDomainMessenger send messages to itself.\\n *\\n * @param _target Address of the contract to check.\\n *\\n * @return Whether or not the address is an unsafe system address.\\n */\\n function _isUnsafeTarget(address _target) internal view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xead7d44e99f3749f1f45e3f70496c27c2d56e532835c13d02b43ee0d8ff1d593\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.15;\\n\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\n\\n/**\\n * @title Semver\\n * @notice Semver is a simple contract for managing contract versions.\\n */\\ncontract Semver {\\n /**\\n * @notice Contract version number (major).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable PATCH_VERSION;\\n\\n /**\\n * @param _major Version number (major).\\n * @param _minor Version number (minor).\\n * @param _patch Version number (patch).\\n */\\n constructor(\\n uint256 _major,\\n uint256 _minor,\\n uint256 _patch\\n ) {\\n MAJOR_VERSION = _major;\\n MINOR_VERSION = _minor;\\n PATCH_VERSION = _patch;\\n }\\n\\n /**\\n * @notice Returns the full semver contract version.\\n *\\n * @return Semver contract version as a string.\\n */\\n function version() public view returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n Strings.toString(MAJOR_VERSION),\\n \\\".\\\",\\n Strings.toString(MINOR_VERSION),\\n \\\".\\\",\\n Strings.toString(PATCH_VERSION)\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x8215e8fbaace5e06fdf0be26cd8ec224847cf03e89bd78dc8ba3ec2cb429d4fe\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\\n * initialization step. This is essential to configure modules that are added through upgrades and that require\\n * initialization.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized < type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x8cc03c5ac17e8a7396e487cda41fc1f1dfdb91db7d528e6da84bee3b6dd7e167\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/L1/L1ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { ERC721Bridge } from \\\"../universal/op-erc721/ERC721Bridge.sol\\\";\\nimport { IERC721 } from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport { L2ERC721Bridge } from \\\"../L2/L2ERC721Bridge.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title L1ERC721Bridge\\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\\n * acts as an escrow for ERC721 tokens deposited into L2.\\n */\\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\\n /**\\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\\n * by ID was deposited for a given L2 token.\\n */\\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(1, 0, 0)\\n ERC721Bridge(_messenger, _otherBridge)\\n {}\\n\\n /*************************\\n * Cross-chain Functions *\\n *************************/\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyOtherBridge {\\n require(_localToken != address(this), \\\"L1ERC721Bridge: local token cannot be self\\\");\\n\\n // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\\n require(\\n deposits[_localToken][_remoteToken][_tokenId] == true,\\n \\\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\\\"\\n );\\n\\n // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\\n // Bridge.\\n deposits[_localToken][_remoteToken][_tokenId] = false;\\n\\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\\n // withdrawer.\\n IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @inheritdoc ERC721Bridge\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal override {\\n require(_remoteToken != address(0), \\\"ERC721Bridge: remote token cannot be address(0)\\\");\\n\\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\\n bytes memory message = abi.encodeWithSelector(\\n L2ERC721Bridge.finalizeBridgeERC721.selector,\\n _remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Lock token into bridge\\n deposits[_localToken][_remoteToken][_tokenId] = true;\\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\\n\\n // Send calldata into L2\\n messenger.sendMessage(otherBridge, message, _minGasLimit);\\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0x966ae750603761f5636063e4d1441759bd7e140ba933303d31c62220e75c8869\",\"license\":\"MIT\"},\"contracts/L2/L2ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { ERC721Bridge } from \\\"../universal/op-erc721/ERC721Bridge.sol\\\";\\nimport { ERC165Checker } from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\nimport { L1ERC721Bridge } from \\\"../L1/L1ERC721Bridge.sol\\\";\\nimport { IOptimismMintableERC721 } from \\\"../universal/op-erc721/IOptimismMintableERC721.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title L2ERC721Bridge\\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\\n * This contract also acts as a burner for tokens being withdrawn.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n */\\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(1, 0, 0)\\n ERC721Bridge(_messenger, _otherBridge)\\n {}\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyOtherBridge {\\n require(_localToken != address(this), \\\"L2ERC721Bridge: local token cannot be self\\\");\\n\\n // Note that supportsInterface makes a callback to the _localToken address which is user\\n // provided.\\n require(\\n ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\\n \\\"L2ERC721Bridge: local token interface is not compliant\\\"\\n );\\n\\n require(\\n _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\\n \\\"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\\\"\\n );\\n\\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\\n // on L2. Note that safeMint makes a callback to the _to address which is user provided.\\n IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @inheritdoc ERC721Bridge\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal override {\\n require(_remoteToken != address(0), \\\"ERC721Bridge: remote token cannot be address(0)\\\");\\n\\n // Check that the withdrawal is being initiated by the NFT owner\\n require(\\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\\n \\\"Withdrawal is not being initiated by NFT owner\\\"\\n );\\n\\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\\n // slither-disable-next-line reentrancy-events\\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\\n require(\\n remoteToken == _remoteToken,\\n \\\"L2ERC721Bridge: remote token does not match given value\\\"\\n );\\n\\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\\n // usage\\n // slither-disable-next-line reentrancy-events\\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\\n\\n bytes memory message = abi.encodeWithSelector(\\n L1ERC721Bridge.finalizeBridgeERC721.selector,\\n remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Send message to L1 bridge\\n // slither-disable-next-line reentrancy-events\\n messenger.sendMessage(otherBridge, message, _minGasLimit);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0xedcf2403f87c8c72790c053b44ccd762e99f5cdf0f362123288d6893b4c856b5\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport {\\n CrossDomainMessenger\\n} from \\\"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\n/**\\n * @title ERC721Bridge\\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\\n */\\nabstract contract ERC721Bridge {\\n /**\\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeInitiated(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFinalized(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Messenger contract on this domain.\\n */\\n CrossDomainMessenger public immutable messenger;\\n\\n /**\\n * @notice Address of the bridge on the other network.\\n */\\n address public immutable otherBridge;\\n\\n /**\\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\\n */\\n uint256[49] private __gap;\\n\\n /**\\n * @notice Ensures that the caller is a cross-chain message from the other bridge.\\n */\\n modifier onlyOtherBridge() {\\n require(\\n msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\\n \\\"ERC721Bridge: function can only be called from the other bridge\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge) {\\n require(_messenger != address(0), \\\"ERC721Bridge: messenger cannot be address(0)\\\");\\n require(_otherBridge != address(0), \\\"ERC721Bridge: other bridge cannot be address(0)\\\");\\n\\n messenger = CrossDomainMessenger(_messenger);\\n otherBridge = _otherBridge;\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\\n * this function can only be called by EOAs. Smart contract wallets should use the\\n * `bridgeERC721To` function after ensuring that the recipient address on the remote\\n * chain exists. Also note that the current owner of the token on this chain must\\n * approve this contract to operate the NFT before it can be bridged.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\\n * be used to execute any code on the other chain and is only emitted as\\n * extra data for the convenience of off-chain tooling.\\n */\\n function bridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n // Modifier requiring sender to be EOA. This prevents against a user error that would occur\\n // if the sender is a smart contract wallet that has a different address on the remote chain\\n // (or doesn't have an address on the remote chain at all). The user would fail to receive\\n // the NFT if they use this function because it sends the NFT to the same address as the\\n // caller. This check could be bypassed by a malicious contract via initcode, but it takes\\n // care of the user error we want to avoid.\\n require(!Address.isContract(msg.sender), \\\"ERC721Bridge: account is not externally owned\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n msg.sender,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\\n * that the current owner of the token on this chain must approve this contract to\\n * operate the NFT before it can be bridged.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\\n * be used to execute any code on the other chain and is only emitted as\\n * extra data for the convenience of off-chain tooling.\\n */\\n function bridgeERC721To(\\n address _localToken,\\n address _remoteToken,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n require(_to != address(0), \\\"ERC721Bridge: nft recipient cannot be address(0)\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n _to,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Internal function for initiating a token bridge to the other domain.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _from Address of the sender on this domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other domain. Data supplied here will\\n * not be used to execute any code on the other domain and is only emitted\\n * as extra data for the convenience of off-chain tooling.\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal virtual;\\n}\\n\",\"keccak256\":\"0x24898e2e75865a4e35cde2d62518cb4c15a30b7cdae8a1a37624a82ae2a26eb7\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/IOptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {\\n IERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\\\";\\n\\n/**\\n * @title IOptimismMintableERC721\\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\\n */\\ninterface IOptimismMintableERC721 is IERC721Enumerable {\\n /**\\n * @notice Emitted when a token is minted.\\n *\\n * @param account Address of the account the token was minted to.\\n * @param tokenId Token ID of the minted token.\\n */\\n event Mint(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Emitted when a token is burned.\\n *\\n * @param account Address of the account the token was burned from.\\n * @param tokenId Token ID of the burned token.\\n */\\n event Burn(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Chain ID of the chain where the remote token is deployed.\\n */\\n function remoteChainId() external view returns (uint256);\\n\\n /**\\n * @notice Address of the token on the remote domain.\\n */\\n function remoteToken() external view returns (address);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n function bridge() external view returns (address);\\n\\n /**\\n * @notice Mints some token ID for a user, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * @param _to Address of the user to mint the token for.\\n * @param _tokenId Token ID to mint.\\n */\\n function safeMint(address _to, uint256 _tokenId) external;\\n\\n /**\\n * @notice Burns a token ID from a user.\\n *\\n * @param _from Address of the user to burn the token from.\\n * @param _tokenId Token ID to burn.\\n */\\n function burn(address _from, uint256 _tokenId) external;\\n}\\n\",\"keccak256\":\"0xc3703030d0093d65839b02296e3152681fa1c8d717e66ab3f5a7c32ba3fd0a54\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6101206040523480156200001257600080fd5b506040516200197238038062001972833981016040819052620000359162000162565b600160008084846001600160a01b038216620000ad5760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b0381166200011d5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401620000a4565b6001600160a01b039182166080521660a05260c09290925260e05261010052506200019a9050565b80516001600160a01b03811681146200015d57600080fd5b919050565b600080604083850312156200017657600080fd5b620001818362000145565b9150620001916020840162000145565b90509250929050565b60805160a05160c05160e051610100516117716200020160003960006102440152600061021b015260006101f201526000818161011d015281816102d00152610d630152600081816091015281816102a6015281816103070152610d3601526117716000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063761f449311610050578063761f4493146100f2578063aa55745214610105578063c89701a21461011857600080fd5b80633687011a146100775780633cb747bf1461008c57806354fd4d50146100dd575b600080fd5b61008a6100853660046111d8565b61013f565b005b6100b37f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100e56101eb565b6040516100d491906112d5565b61008a6101003660046112e8565b61028e565b61008a610113366004611380565b6107f5565b6100b37f000000000000000000000000000000000000000000000000000000000000000081565b333b156101d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6101e386863333888888886108b1565b505050505050565b60606102167f0000000000000000000000000000000000000000000000000000000000000000610e4f565b61023f7f0000000000000000000000000000000000000000000000000000000000000000610e4f565b6102687f0000000000000000000000000000000000000000000000000000000000000000610e4f565b60405160200161027a939291906113f7565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103ac57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610370573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610394919061146d565b73ffffffffffffffffffffffffffffffffffffffff16145b610438576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016101ca565b3073ffffffffffffffffffffffffffffffffffffffff8816036104dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016101ca565b610507877fe49bc7f800000000000000000000000000000000000000000000000000000000610f8c565b610593576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e20696e746560448201527f7266616365206973206e6f7420636f6d706c69616e740000000000000000000060648201526084016101ca565b8673ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610602919061146d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146106e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324552433732314272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433732312060648201527f6c6f63616c20746f6b656e000000000000000000000000000000000000000000608482015260a4016101ca565b6040517fa144819400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063a144819490604401600060405180830381600087803b15801561075257600080fd5b505af1158015610766573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107e494939291906114da565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610898576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016101ca565b6108a887873388888888886108b1565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff8716610954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4552433732314272696467653a2072656d6f746520746f6b656e2063616e6e6f60448201527f742062652061646472657373283029000000000000000000000000000000000060648201526084016101ca565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e90602401602060405180830381865afa1580156109bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e3919061146d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f5769746864726177616c206973206e6f74206265696e6720696e69746961746560448201527f64206279204e4654206f776e657200000000000000000000000000000000000060648201526084016101ca565b60008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610aea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0e919061146d565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c756500000000000000000060648201526084016101ca565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790528a1690639dc29fac90604401600060405180830381600087803b158015610c3b57600080fd5b505af1158015610c4f573d6000803e3d6000fd5b50505050600063761f449360e01b828b8a8a8a8989604051602401610c7a9796959493929190611510565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f3dbb202b00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633dbb202b90610d8f907f00000000000000000000000000000000000000000000000000000000000000009085908a9060040161156d565b600060405180830381600087803b158015610da957600080fd5b505af1158015610dbd573d6000803e3d6000fd5b505050508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610e3b94939291906114da565b60405180910390a450505050505050505050565b606081600003610e9257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610ebc5780610ea6816115e1565b9150610eb59050600a83611648565b9150610e96565b60008167ffffffffffffffff811115610ed757610ed761165c565b6040519080825280601f01601f191660200182016040528015610f01576020820181803683370190505b5090505b8415610f8457610f1660018361168b565b9150610f23600a866116a2565b610f2e9060306116b6565b60f81b818381518110610f4357610f436116ce565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610f7d600a86611648565b9450610f05565b949350505050565b6000610f9783610fb1565b8015610fa85750610fa88383611015565b90505b92915050565b6000610fdd827f01ffc9a700000000000000000000000000000000000000000000000000000000611015565b8015610fab575061100e827fffffffff00000000000000000000000000000000000000000000000000000000611015565b1592915050565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a7000000000000000000000000000000000000000000000000000000001790529051600091908290819073ffffffffffffffffffffffffffffffffffffffff871690617530906110cf9086906116fd565b6000604051808303818686fa925050503d806000811461110b576040519150601f19603f3d011682016040523d82523d6000602084013e611110565b606091505b509150915060208151101561112b5760009350505050610fab565b8180156111475750808060200190518101906111479190611719565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461117357600080fd5b50565b803563ffffffff8116811461118a57600080fd5b919050565b60008083601f8401126111a157600080fd5b50813567ffffffffffffffff8111156111b957600080fd5b6020830191508360208285010111156111d157600080fd5b9250929050565b60008060008060008060a087890312156111f157600080fd5b86356111fc81611151565b9550602087013561120c81611151565b94506040870135935061122160608801611176565b9250608087013567ffffffffffffffff81111561123d57600080fd5b61124989828a0161118f565b979a9699509497509295939492505050565b60005b8381101561127657818101518382015260200161125e565b83811115611285576000848401525b50505050565b600081518084526112a381602086016020860161125b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610fa8602083018461128b565b600080600080600080600060c0888a03121561130357600080fd5b873561130e81611151565b9650602088013561131e81611151565b9550604088013561132e81611151565b9450606088013561133e81611151565b93506080880135925060a088013567ffffffffffffffff81111561136157600080fd5b61136d8a828b0161118f565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561139b57600080fd5b87356113a681611151565b965060208801356113b681611151565b955060408801356113c681611151565b9450606088013593506113db60808901611176565b925060a088013567ffffffffffffffff81111561136157600080fd5b6000845161140981846020890161125b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611445816001850160208a0161125b565b6001920191820152835161146081600284016020880161125b565b0160020195945050505050565b60006020828403121561147f57600080fd5b815161148a81611151565b9392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611147606083018486611491565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261156060c083018486611491565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061159c606083018561128b565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611612576116126115b2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165757611657611619565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008282101561169d5761169d6115b2565b500390565b6000826116b1576116b1611619565b500690565b600082198211156116c9576116c96115b2565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825161170f81846020870161125b565b9190910192915050565b60006020828403121561172b57600080fd5b8151801515811461148a57600080fdfea264697066735822122038ebf17853e671ca85694dc6b63a39fe1ec7d19a5f56e16bf6790e2e0b0569e764736f6c634300080f0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063761f449311610050578063761f4493146100f2578063aa55745214610105578063c89701a21461011857600080fd5b80633687011a146100775780633cb747bf1461008c57806354fd4d50146100dd575b600080fd5b61008a6100853660046111d8565b61013f565b005b6100b37f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100e56101eb565b6040516100d491906112d5565b61008a6101003660046112e8565b61028e565b61008a610113366004611380565b6107f5565b6100b37f000000000000000000000000000000000000000000000000000000000000000081565b333b156101d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6101e386863333888888886108b1565b505050505050565b60606102167f0000000000000000000000000000000000000000000000000000000000000000610e4f565b61023f7f0000000000000000000000000000000000000000000000000000000000000000610e4f565b6102687f0000000000000000000000000000000000000000000000000000000000000000610e4f565b60405160200161027a939291906113f7565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103ac57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610370573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610394919061146d565b73ffffffffffffffffffffffffffffffffffffffff16145b610438576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016101ca565b3073ffffffffffffffffffffffffffffffffffffffff8816036104dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016101ca565b610507877fe49bc7f800000000000000000000000000000000000000000000000000000000610f8c565b610593576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e20696e746560448201527f7266616365206973206e6f7420636f6d706c69616e740000000000000000000060648201526084016101ca565b8673ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610602919061146d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146106e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324552433732314272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433732312060648201527f6c6f63616c20746f6b656e000000000000000000000000000000000000000000608482015260a4016101ca565b6040517fa144819400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063a144819490604401600060405180830381600087803b15801561075257600080fd5b505af1158015610766573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107e494939291906114da565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610898576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016101ca565b6108a887873388888888886108b1565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff8716610954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4552433732314272696467653a2072656d6f746520746f6b656e2063616e6e6f60448201527f742062652061646472657373283029000000000000000000000000000000000060648201526084016101ca565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e90602401602060405180830381865afa1580156109bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e3919061146d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f5769746864726177616c206973206e6f74206265696e6720696e69746961746560448201527f64206279204e4654206f776e657200000000000000000000000000000000000060648201526084016101ca565b60008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610aea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0e919061146d565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c756500000000000000000060648201526084016101ca565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790528a1690639dc29fac90604401600060405180830381600087803b158015610c3b57600080fd5b505af1158015610c4f573d6000803e3d6000fd5b50505050600063761f449360e01b828b8a8a8a8989604051602401610c7a9796959493929190611510565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f3dbb202b00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633dbb202b90610d8f907f00000000000000000000000000000000000000000000000000000000000000009085908a9060040161156d565b600060405180830381600087803b158015610da957600080fd5b505af1158015610dbd573d6000803e3d6000fd5b505050508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610e3b94939291906114da565b60405180910390a450505050505050505050565b606081600003610e9257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610ebc5780610ea6816115e1565b9150610eb59050600a83611648565b9150610e96565b60008167ffffffffffffffff811115610ed757610ed761165c565b6040519080825280601f01601f191660200182016040528015610f01576020820181803683370190505b5090505b8415610f8457610f1660018361168b565b9150610f23600a866116a2565b610f2e9060306116b6565b60f81b818381518110610f4357610f436116ce565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610f7d600a86611648565b9450610f05565b949350505050565b6000610f9783610fb1565b8015610fa85750610fa88383611015565b90505b92915050565b6000610fdd827f01ffc9a700000000000000000000000000000000000000000000000000000000611015565b8015610fab575061100e827fffffffff00000000000000000000000000000000000000000000000000000000611015565b1592915050565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a7000000000000000000000000000000000000000000000000000000001790529051600091908290819073ffffffffffffffffffffffffffffffffffffffff871690617530906110cf9086906116fd565b6000604051808303818686fa925050503d806000811461110b576040519150601f19603f3d011682016040523d82523d6000602084013e611110565b606091505b509150915060208151101561112b5760009350505050610fab565b8180156111475750808060200190518101906111479190611719565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461117357600080fd5b50565b803563ffffffff8116811461118a57600080fd5b919050565b60008083601f8401126111a157600080fd5b50813567ffffffffffffffff8111156111b957600080fd5b6020830191508360208285010111156111d157600080fd5b9250929050565b60008060008060008060a087890312156111f157600080fd5b86356111fc81611151565b9550602087013561120c81611151565b94506040870135935061122160608801611176565b9250608087013567ffffffffffffffff81111561123d57600080fd5b61124989828a0161118f565b979a9699509497509295939492505050565b60005b8381101561127657818101518382015260200161125e565b83811115611285576000848401525b50505050565b600081518084526112a381602086016020860161125b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610fa8602083018461128b565b600080600080600080600060c0888a03121561130357600080fd5b873561130e81611151565b9650602088013561131e81611151565b9550604088013561132e81611151565b9450606088013561133e81611151565b93506080880135925060a088013567ffffffffffffffff81111561136157600080fd5b61136d8a828b0161118f565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561139b57600080fd5b87356113a681611151565b965060208801356113b681611151565b955060408801356113c681611151565b9450606088013593506113db60808901611176565b925060a088013567ffffffffffffffff81111561136157600080fd5b6000845161140981846020890161125b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611445816001850160208a0161125b565b6001920191820152835161146081600284016020880161125b565b0160020195945050505050565b60006020828403121561147f57600080fd5b815161148a81611151565b9392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611147606083018486611491565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261156060c083018486611491565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061159c606083018561128b565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611612576116126115b2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165757611657611619565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008282101561169d5761169d6115b2565b500390565b6000826116b1576116b1611619565b500690565b600082198211156116c9576116c96115b2565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825161170f81846020870161125b565b9190910192915050565b60006020828403121561172b57600080fd5b8151801515811461148a57600080fdfea264697066735822122038ebf17853e671ca85694dc6b63a39fe1ec7d19a5f56e16bf6790e2e0b0569e764736f6c634300080f0033", + "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": { + "custom:semver": "1.0.0", + "params": { + "_messenger": "Address of the CrossDomainMessenger on this network.", + "_otherBridge": "Address of the ERC721 bridge on the other network." + } + }, + "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { + "params": { + "_extraData": "Optional data to forward to L1. Data supplied here will not be used to execute any code on L1 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." + } + }, + "version()": { + "returns": { + "_0": "Semver contract version as a string." + } + } + }, + "title": "L2ERC721Bridge", + "version": 1 + }, + "userdoc": { + "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." + } + }, + "kind": "user", + "methods": { + "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." + }, + "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." + }, + "messenger()": { + "notice": "Messenger contract on this domain." + }, + "otherBridge()": { + "notice": "Address of the bridge on the other network." + }, + "version()": { + "notice": "Returns the full semver contract version." + } + }, + "notice": "The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge. This contract also acts as a burner for tokens being withdrawn. **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.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 8088, + "contract": "contracts/L2/L2ERC721Bridge.sol:L2ERC721Bridge", + "label": "__gap", + "offset": 0, + "slot": "0", + "type": "t_array(t_uint256)49_storage" + } + ], + "types": { + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-goerli/L2ERC721BridgeProxy.json b/packages/contracts-periphery/deployments/optimism-goerli/L2ERC721BridgeProxy.json new file mode 100644 index 0000000000000..7b340b91992b5 --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism-goerli/L2ERC721BridgeProxy.json @@ -0,0 +1,257 @@ +{ + "address": "0x4200000000000000000000000000000000000014", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x651e799090ad8368e9950399918ebaca75b4c50b030a211d4db139849c628902", + "receipt": { + "to": null, + "from": "0x5c679a57e018F5F146838138d3E032Ef4913D551", + "contractAddress": "0x4200000000000000000000000000000000000014", + "transactionIndex": 0, + "gasUsed": "532674", + "logsBloom": "0x00000000000000000000000000000000000000000000200000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000008000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x93b7b9ef8fb4874e7ca905a3fd375e14c32b863072b7e8cb8c02789f9827122b", + "transactionHash": "0x651e799090ad8368e9950399918ebaca75b4c50b030a211d4db139849c628902", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 1562987, + "transactionHash": "0x651e799090ad8368e9950399918ebaca75b4c50b030a211d4db139849c628902", + "address": "0x4200000000000000000000000000000000000014", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000005c679a57e018f5f146838138d3e032ef4913d551", + "logIndex": 0, + "blockHash": "0x93b7b9ef8fb4874e7ca905a3fd375e14c32b863072b7e8cb8c02789f9827122b" + } + ], + "blockNumber": 1562987, + "cumulativeGasUsed": "532674", + "status": 1, + "byzantium": true + }, + "args": [ + "0x5c679a57e018F5F146838138d3E032Ef4913D551" + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"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\"}}},\"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.\"}}},\"title\":\"Proxy\",\"version\":1},\"userdoc\":{\"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.\"}},\"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.\"},\"implementation()\":{\"notice\":\"Queries the implementation address.\"},\"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.\"}},\"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.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title Proxy\\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\\n * if the caller is address(0), meaning that the call originated from an off-chain\\n * simulation.\\n */\\ncontract Proxy {\\n /**\\n * @notice The storage slot that holds the address of the implementation.\\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n */\\n bytes32 internal constant IMPLEMENTATION_KEY =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @notice The storage slot that holds the address of the owner.\\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n */\\n bytes32 internal constant OWNER_KEY =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @notice An event that is emitted each time the implementation is changed. This event is part\\n * of the EIP-1967 specification.\\n *\\n * @param implementation The address of the implementation contract\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\\n * EIP-1967 specification.\\n *\\n * @param previousAdmin The previous owner of the contract\\n * @param newAdmin The new owner of the contract\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\\n * eth_call to interact with this proxy without needing to use low-level storage\\n * inspection. We assume that nobody is able to trigger calls from address(0) during\\n * normal EVM execution.\\n */\\n modifier proxyCallIfNotAdmin() {\\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\\n _;\\n } else {\\n // This WILL halt the call frame on completion.\\n _doProxyCall();\\n }\\n }\\n\\n /**\\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\\n * EIP-1967 admin storage slot so that accidental storage collision with the\\n * implementation is not possible.\\n *\\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\\n * transparent proxy interface.\\n */\\n constructor(address _admin) {\\n _changeAdmin(_admin);\\n }\\n\\n // slither-disable-next-line locked-ether\\n receive() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n // slither-disable-next-line locked-ether\\n fallback() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n /**\\n * @notice Set the implementation contract address. The code at the given address will execute\\n * when this contract is called.\\n *\\n * @param _implementation Address of the implementation contract.\\n */\\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\\n _setImplementation(_implementation);\\n }\\n\\n /**\\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\\n * atomic execution of initialization-based upgrades.\\n *\\n * @param _implementation Address of the implementation contract.\\n * @param _data Calldata to delegatecall the new implementation with.\\n */\\n function upgradeToAndCall(address _implementation, bytes calldata _data)\\n external\\n payable\\n proxyCallIfNotAdmin\\n returns (bytes memory)\\n {\\n _setImplementation(_implementation);\\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\\n require(success, \\\"Proxy: delegatecall to new implementation contract failed\\\");\\n return returndata;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\\n _changeAdmin(_admin);\\n }\\n\\n /**\\n * @notice Gets the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function admin() external proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() external proxyCallIfNotAdmin returns (address) {\\n return _getImplementation();\\n }\\n\\n /**\\n * @notice Sets the implementation address.\\n *\\n * @param _implementation New implementation address.\\n */\\n function _setImplementation(address _implementation) internal {\\n assembly {\\n sstore(IMPLEMENTATION_KEY, _implementation)\\n }\\n emit Upgraded(_implementation);\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function _changeAdmin(address _admin) internal {\\n address previous = _getAdmin();\\n assembly {\\n sstore(OWNER_KEY, _admin)\\n }\\n emit AdminChanged(previous, _admin);\\n }\\n\\n /**\\n * @notice Performs the proxy call via a delegatecall.\\n */\\n function _doProxyCall() internal {\\n address impl = _getImplementation();\\n require(impl != address(0), \\\"Proxy: implementation not initialized\\\");\\n\\n assembly {\\n // Copy calldata into memory at 0x0....calldatasize.\\n calldatacopy(0x0, 0x0, calldatasize())\\n\\n // Perform the delegatecall, make sure to pass all available gas.\\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\\n\\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\\n // overwrite the calldata that we just copied into memory but that doesn't really\\n // matter because we'll be returning in a second anyway.\\n returndatacopy(0x0, 0x0, returndatasize())\\n\\n // Success == 0 means a revert. We'll revert too and pass the data up.\\n if iszero(success) {\\n revert(0x0, returndatasize())\\n }\\n\\n // Otherwise we'll just return and pass the data up.\\n return(0x0, returndatasize())\\n }\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n address impl;\\n assembly {\\n impl := sload(IMPLEMENTATION_KEY)\\n }\\n return impl;\\n }\\n\\n /**\\n * @notice Queries the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function _getAdmin() internal view returns (address) {\\n address owner;\\n assembly {\\n owner := sload(OWNER_KEY)\\n }\\n return owner;\\n }\\n}\\n\",\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5060405161094138038061094183398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206109218339815191525490565b600080516020610921833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610830806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033", + "devdoc": { + "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" + } + } + }, + "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." + } + } + }, + "title": "Proxy", + "version": 1 + }, + "userdoc": { + "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." + } + }, + "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." + }, + "implementation()": { + "notice": "Queries the implementation address." + }, + "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." + } + }, + "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.", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-goerli/OptimismMintableERC721Factory.json b/packages/contracts-periphery/deployments/optimism-goerli/OptimismMintableERC721Factory.json new file mode 100644 index 0000000000000..27974701f34d3 --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism-goerli/OptimismMintableERC721Factory.json @@ -0,0 +1,250 @@ +{ + "address": "0xeb40ef4A266D162d18ed8C70bafCa77fC1F3e489", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bridge", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_remoteChainId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "deployer", + "type": "address" + } + ], + "name": "OptimismMintableERC721Created", + "type": "event" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_remoteToken", + "type": "address" + }, + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + } + ], + "name": "createOptimismMintableERC721", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isOptimismMintableERC721", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "remoteChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xc518251aab92c03f645f192efd42d0dc7c9266929a7940dd166b7c6e6e99811d", + "receipt": { + "to": null, + "from": "0x5c679a57e018F5F146838138d3E032Ef4913D551", + "contractAddress": "0xeb40ef4A266D162d18ed8C70bafCa77fC1F3e489", + "transactionIndex": 0, + "gasUsed": "3124569", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x63a9f4d27f3f9e1e0d290b591cbd1b887b54ecb4f248fdbe28aae4c333fc97fb", + "transactionHash": "0xc518251aab92c03f645f192efd42d0dc7c9266929a7940dd166b7c6e6e99811d", + "logs": [], + "blockNumber": 1563190, + "cumulativeGasUsed": "3124569", + "status": 1, + "byzantium": true + }, + "args": [ + "0x4200000000000000000000000000000000000014", + 5 + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_remoteChainId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\"}],\"name\":\"OptimismMintableERC721Created\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createOptimismMintableERC721\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isOptimismMintableERC721\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"remoteChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"OptimismMintableERC721Created(address,address,address)\":{\"params\":{\"deployer\":\"Address of the initiator of the deployment\",\"localToken\":\"Address of the token on the this domain.\",\"remoteToken\":\"Address of the token on the remote domain.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_bridge\":\"Address of the ERC721 bridge on this network.\"}},\"createOptimismMintableERC721(address,string,string)\":{\"params\":{\"_name\":\"ERC721 name.\",\"_remoteToken\":\"Address of the corresponding token on the other domain.\",\"_symbol\":\"ERC721 symbol.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"OptimismMintableERC721Factory\",\"version\":1},\"userdoc\":{\"events\":{\"OptimismMintableERC721Created(address,address,address)\":{\"notice\":\"Emitted whenever a new OptimismMintableERC721 contract is created.\"}},\"kind\":\"user\",\"methods\":{\"bridge()\":{\"notice\":\"Address of the ERC721 bridge on this network.\"},\"createOptimismMintableERC721(address,string,string)\":{\"notice\":\"Creates an instance of the standard ERC721.\"},\"isOptimismMintableERC721(address)\":{\"notice\":\"Tracks addresses created by this factory.\"},\"remoteChainId()\":{\"notice\":\"Chain ID for the remote network.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"Factory contract for creating OptimismMintableERC721 contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-erc721/OptimismMintableERC721Factory.sol\":\"OptimismMintableERC721Factory\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.15;\\n\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\n\\n/**\\n * @title Semver\\n * @notice Semver is a simple contract for managing contract versions.\\n */\\ncontract Semver {\\n /**\\n * @notice Contract version number (major).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable PATCH_VERSION;\\n\\n /**\\n * @param _major Version number (major).\\n * @param _minor Version number (minor).\\n * @param _patch Version number (patch).\\n */\\n constructor(\\n uint256 _major,\\n uint256 _minor,\\n uint256 _patch\\n ) {\\n MAJOR_VERSION = _major;\\n MINOR_VERSION = _minor;\\n PATCH_VERSION = _patch;\\n }\\n\\n /**\\n * @notice Returns the full semver contract version.\\n *\\n * @return Semver contract version as a string.\\n */\\n function version() public view returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n Strings.toString(MAJOR_VERSION),\\n \\\".\\\",\\n Strings.toString(MINOR_VERSION),\\n \\\".\\\",\\n Strings.toString(PATCH_VERSION)\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x8215e8fbaace5e06fdf0be26cd8ec224847cf03e89bd78dc8ba3ec2cb429d4fe\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _owners[tokenId];\\n require(owner != address(0), \\\"ERC721: owner query for nonexistent token\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overridden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n _safeTransfer(from, to, tokenId, _data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _owners[tokenId] != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, _data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId);\\n\\n _balances[to] += 1;\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n\\n _afterTokenTransfer(address(0), to, tokenId);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n // Clear approvals\\n _approve(address(0), tokenId);\\n\\n _balances[owner] -= 1;\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n\\n _afterTokenTransfer(owner, address(0), tokenId);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId);\\n\\n // Clear approvals from the previous owner\\n _approve(address(0), tokenId);\\n\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n\\n _afterTokenTransfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits a {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits a {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(\\n address owner,\\n address operator,\\n bool approved\\n ) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param _data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n * transferred to `to`.\\n * - When `from` is zero, `tokenId` will be minted for `to`.\\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x921f012325281f7d81e29c53a13824cf6c2c5d77232065d0d4f3f912e97af6ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC721.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\n\\n/**\\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\\n * enumerability of all the token ids in the contract as well as all token ids owned by each\\n * account.\\n */\\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\\n // Mapping from owner to list of owned token IDs\\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\\n\\n // Mapping from token ID to index of the owner tokens list\\n mapping(uint256 => uint256) private _ownedTokensIndex;\\n\\n // Array with all token ids, used for enumeration\\n uint256[] private _allTokens;\\n\\n // Mapping from token id to position in the allTokens array\\n mapping(uint256 => uint256) private _allTokensIndex;\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n require(index < ERC721.balanceOf(owner), \\\"ERC721Enumerable: owner index out of bounds\\\");\\n return _ownedTokens[owner][index];\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _allTokens.length;\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-tokenByIndex}.\\n */\\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n require(index < ERC721Enumerable.totalSupply(), \\\"ERC721Enumerable: global index out of bounds\\\");\\n return _allTokens[index];\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n * transferred to `to`.\\n * - When `from` is zero, `tokenId` will be minted for `to`.\\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual override {\\n super._beforeTokenTransfer(from, to, tokenId);\\n\\n if (from == address(0)) {\\n _addTokenToAllTokensEnumeration(tokenId);\\n } else if (from != to) {\\n _removeTokenFromOwnerEnumeration(from, tokenId);\\n }\\n if (to == address(0)) {\\n _removeTokenFromAllTokensEnumeration(tokenId);\\n } else if (to != from) {\\n _addTokenToOwnerEnumeration(to, tokenId);\\n }\\n }\\n\\n /**\\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\\n * @param to address representing the new owner of the given token ID\\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\\n */\\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\\n uint256 length = ERC721.balanceOf(to);\\n _ownedTokens[to][length] = tokenId;\\n _ownedTokensIndex[tokenId] = length;\\n }\\n\\n /**\\n * @dev Private function to add a token to this extension's token tracking data structures.\\n * @param tokenId uint256 ID of the token to be added to the tokens list\\n */\\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\\n _allTokensIndex[tokenId] = _allTokens.length;\\n _allTokens.push(tokenId);\\n }\\n\\n /**\\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\\n * @param from address representing the previous owner of the given token ID\\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\\n */\\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\\n // then delete the last slot (swap and pop).\\n\\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\\n\\n // When the token to delete is the last token, the swap operation is unnecessary\\n if (tokenIndex != lastTokenIndex) {\\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\\n\\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\\n }\\n\\n // This also deletes the contents at the last position of the array\\n delete _ownedTokensIndex[tokenId];\\n delete _ownedTokens[from][lastTokenIndex];\\n }\\n\\n /**\\n * @dev Private function to remove a token from this extension's token tracking data structures.\\n * This has O(1) time complexity, but alters the order of the _allTokens array.\\n * @param tokenId uint256 ID of the token to be removed from the tokens list\\n */\\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\\n // then delete the last slot (swap and pop).\\n\\n uint256 lastTokenIndex = _allTokens.length - 1;\\n uint256 tokenIndex = _allTokensIndex[tokenId];\\n\\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\\n uint256 lastTokenId = _allTokens[lastTokenIndex];\\n\\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\\n\\n // This also deletes the contents at the last position of the array\\n delete _allTokensIndex[tokenId];\\n _allTokens.pop();\\n }\\n}\\n\",\"keccak256\":\"0x0a79511df8151b10b0a0004d6a76ad956582d32824af4c0f4886bdbdfe5746e5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/IOptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {\\n IERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\\\";\\n\\n/**\\n * @title IOptimismMintableERC721\\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\\n */\\ninterface IOptimismMintableERC721 is IERC721Enumerable {\\n /**\\n * @notice Emitted when a token is minted.\\n *\\n * @param account Address of the account the token was minted to.\\n * @param tokenId Token ID of the minted token.\\n */\\n event Mint(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Emitted when a token is burned.\\n *\\n * @param account Address of the account the token was burned from.\\n * @param tokenId Token ID of the burned token.\\n */\\n event Burn(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Chain ID of the chain where the remote token is deployed.\\n */\\n function remoteChainId() external view returns (uint256);\\n\\n /**\\n * @notice Address of the token on the remote domain.\\n */\\n function remoteToken() external view returns (address);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n function bridge() external view returns (address);\\n\\n /**\\n * @notice Mints some token ID for a user, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * @param _to Address of the user to mint the token for.\\n * @param _tokenId Token ID to mint.\\n */\\n function safeMint(address _to, uint256 _tokenId) external;\\n\\n /**\\n * @notice Burns a token ID from a user.\\n *\\n * @param _from Address of the user to burn the token from.\\n * @param _tokenId Token ID to burn.\\n */\\n function burn(address _from, uint256 _tokenId) external;\\n}\\n\",\"keccak256\":\"0xc3703030d0093d65839b02296e3152681fa1c8d717e66ab3f5a7c32ba3fd0a54\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/OptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {\\n ERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\\\";\\nimport { ERC721 } from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport { IERC165 } from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport { IOptimismMintableERC721 } from \\\"./IOptimismMintableERC721.sol\\\";\\n\\n/**\\n * @title OptimismMintableERC721\\n * @notice This contract is the remote representation for some token that lives on another network,\\n * typically an Optimism representation of an Ethereum-based token. Standard reference\\n * implementation that can be extended or modified according to your needs.\\n */\\ncontract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n uint256 public immutable remoteChainId;\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n address public immutable remoteToken;\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n address public immutable bridge;\\n\\n /**\\n * @notice Base token URI for this token.\\n */\\n string public baseTokenURI;\\n\\n /**\\n * @param _bridge Address of the bridge on this network.\\n * @param _remoteChainId Chain ID where the remote token is deployed.\\n * @param _remoteToken Address of the corresponding token on the other network.\\n * @param _name ERC721 name.\\n * @param _symbol ERC721 symbol.\\n */\\n constructor(\\n address _bridge,\\n uint256 _remoteChainId,\\n address _remoteToken,\\n string memory _name,\\n string memory _symbol\\n ) ERC721(_name, _symbol) {\\n require(_bridge != address(0), \\\"OptimismMintableERC721: bridge cannot be address(0)\\\");\\n require(_remoteChainId != 0, \\\"OptimismMintableERC721: remote chain id cannot be zero\\\");\\n require(\\n _remoteToken != address(0),\\n \\\"OptimismMintableERC721: remote token cannot be address(0)\\\"\\n );\\n\\n remoteChainId = _remoteChainId;\\n remoteToken = _remoteToken;\\n bridge = _bridge;\\n\\n // Creates a base URI in the format specified by EIP-681:\\n // https://eips.ethereum.org/EIPS/eip-681\\n baseTokenURI = string(\\n abi.encodePacked(\\n \\\"ethereum:\\\",\\n Strings.toHexString(uint160(_remoteToken), 20),\\n \\\"@\\\",\\n Strings.toString(_remoteChainId),\\n \\\"/tokenURI?uint256=\\\"\\n )\\n );\\n }\\n\\n /**\\n * @notice Modifier that prevents callers other than the bridge from calling the function.\\n */\\n modifier onlyBridge() {\\n require(msg.sender == bridge, \\\"OptimismMintableERC721: only bridge can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {\\n _safeMint(_to, _tokenId);\\n\\n emit Mint(_to, _tokenId);\\n }\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n function burn(address _from, uint256 _tokenId) external virtual onlyBridge {\\n _burn(_tokenId);\\n\\n emit Burn(_from, _tokenId);\\n }\\n\\n /**\\n * @notice Checks if a given interface ID is supported by this contract.\\n *\\n * @param _interfaceId The interface ID to check.\\n *\\n * @return True if the interface ID is supported, false otherwise.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n override(ERC721Enumerable, IERC165)\\n returns (bool)\\n {\\n bytes4 iface1 = type(IERC165).interfaceId;\\n bytes4 iface2 = type(IOptimismMintableERC721).interfaceId;\\n return\\n _interfaceId == iface1 ||\\n _interfaceId == iface2 ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n /**\\n * @notice Returns the base token URI.\\n *\\n * @return Base token URI.\\n */\\n function _baseURI() internal view virtual override returns (string memory) {\\n return baseTokenURI;\\n }\\n}\\n\",\"keccak256\":\"0x5ab0e15ecf5617db181396e9c95087fb403e3276527b6426ae3845ec50514d36\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/OptimismMintableERC721Factory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { OptimismMintableERC721 } from \\\"./OptimismMintableERC721.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title OptimismMintableERC721Factory\\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\\n */\\ncontract OptimismMintableERC721Factory is Semver {\\n /**\\n * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\\n *\\n * @param localToken Address of the token on the this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param deployer Address of the initiator of the deployment\\n */\\n event OptimismMintableERC721Created(\\n address indexed localToken,\\n address indexed remoteToken,\\n address deployer\\n );\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n address public immutable bridge;\\n\\n /**\\n * @notice Chain ID for the remote network.\\n */\\n uint256 public immutable remoteChainId;\\n\\n /**\\n * @notice Tracks addresses created by this factory.\\n */\\n mapping(address => bool) public isOptimismMintableERC721;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _bridge Address of the ERC721 bridge on this network.\\n */\\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 0, 0) {\\n require(\\n _bridge != address(0),\\n \\\"OptimismMintableERC721Factory: bridge cannot be address(0)\\\"\\n );\\n require(\\n _remoteChainId != 0,\\n \\\"OptimismMintableERC721Factory: remote chain id cannot be zero\\\"\\n );\\n\\n bridge = _bridge;\\n remoteChainId = _remoteChainId;\\n }\\n\\n /**\\n * @notice Creates an instance of the standard ERC721.\\n *\\n * @param _remoteToken Address of the corresponding token on the other domain.\\n * @param _name ERC721 name.\\n * @param _symbol ERC721 symbol.\\n */\\n function createOptimismMintableERC721(\\n address _remoteToken,\\n string memory _name,\\n string memory _symbol\\n ) external returns (address) {\\n require(\\n _remoteToken != address(0),\\n \\\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\\\"\\n );\\n\\n address localToken = address(\\n new OptimismMintableERC721(bridge, remoteChainId, _remoteToken, _name, _symbol)\\n );\\n\\n isOptimismMintableERC721[localToken] = true;\\n emit OptimismMintableERC721Created(localToken, _remoteToken, msg.sender);\\n\\n return localToken;\\n }\\n}\\n\",\"keccak256\":\"0xf53ee39e9ca7baa5d1c234e58068f9195be1d4c5180a4862356de86294563ba5\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b506040516139b33803806139b38339810160408190526100309161014d565b6001608052600060a081905260c0526001600160a01b0382166100c05760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a206260448201527f72696467652063616e6e6f74206265206164647265737328302900000000000060648201526084015b60405180910390fd5b806000036101365760405162461bcd60e51b815260206004820152603d60248201527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a207260448201527f656d6f746520636861696e2069642063616e6e6f74206265207a65726f00000060648201526084016100b7565b6001600160a01b0390911660e05261010052610187565b6000806040838503121561016057600080fd5b82516001600160a01b038116811461017757600080fd5b6020939093015192949293505050565b60805160a05160c05160e051610100516137da6101d960003960008181610138015261030a01526000818161011001526102e9015260006101c70152600061019c0152600061017101526137da6000f3fe60806040523480156200001157600080fd5b50600436106200006f5760003560e01c8063d97df6521162000056578063d97df65214620000cd578063e78cea92146200010a578063e9518196146200013257600080fd5b806354fd4d5014620000745780635572acae1462000096575b600080fd5b6200007e62000169565b6040516200008d9190620005dc565b60405180910390f35b620000bc620000a736600462000622565b60006020819052908152604090205460ff1681565b60405190151581526020016200008d565b620000e4620000de36600462000722565b62000214565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200008d565b620000e47f000000000000000000000000000000000000000000000000000000000000000081565b6200015a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016200008d565b6060620001967f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001c17f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001ec7f0000000000000000000000000000000000000000000000000000000000000000620003fa565b60405160200162000200939291906200079f565b604051602081830303815290604052905090565b600073ffffffffffffffffffffffffffffffffffffffff8416620002e5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a204c908201527f3120746f6b656e20616464726573732063616e6e6f742062652061646472657360648201527f7328302900000000000000000000000000000000000000000000000000000000608482015260a40160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008686866040516200033a906200054f565b6200034a9594939291906200081b565b604051809103906000f08015801562000367573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff8181166000818152602081815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590513381529394509188169290917fe72783bb8e0ca31286b85278da59684dd814df9762a52f0837f89edd1483b299910160405180910390a3949350505050565b6060816000036200043e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156200046e57806200045581620008ab565b9150620004669050600a8362000915565b915062000442565b60008167ffffffffffffffff8111156200048c576200048c62000640565b6040519080825280601f01601f191660200182016040528015620004b7576020820181803683370190505b5090505b84156200054757620004cf6001836200092c565b9150620004de600a8662000946565b620004eb9060306200095d565b60f81b81838151811062000503576200050362000978565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506200053f600a8662000915565b9450620004bb565b949350505050565b612dfd80620009a883390190565b60005b838110156200057a57818101518382015260200162000560565b838111156200058a576000848401525b50505050565b60008151808452620005aa8160208601602086016200055d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005f1602083018462000590565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061d57600080fd5b919050565b6000602082840312156200063557600080fd5b620005f182620005f8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200068157600080fd5b813567ffffffffffffffff808211156200069f576200069f62000640565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006e857620006e862000640565b816040528381528660208588010111156200070257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200073857600080fd5b6200074384620005f8565b9250602084013567ffffffffffffffff808211156200076157600080fd5b6200076f878388016200066f565b935060408601359150808211156200078657600080fd5b5062000795868287016200066f565b9150509250925092565b60008451620007b38184602089016200055d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551620007f1816001850160208a016200055d565b600192019182015283516200080e8160028401602088016200055d565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835286602084015280861660408401525060a060608301526200085c60a083018562000590565b828103608084015262000870818562000590565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620008df57620008df6200087c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082620009275762000927620008e6565b500490565b6000828210156200094157620009416200087c565b500390565b600082620009585762000958620008e6565b500690565b600082198211156200097357620009736200087c565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe60e06040523480156200001157600080fd5b5060405162002dfd38038062002dfd83398101604081905262000034916200062d565b8181600062000044838262000756565b50600162000053828262000756565b5050506001600160a01b038516620000d85760405162461bcd60e51b815260206004820152603360248201527f4f7074696d69736d4d696e7461626c654552433732313a20627269646765206360448201527f616e6e6f7420626520616464726573732830290000000000000000000000000060648201526084015b60405180910390fd5b83600003620001505760405162461bcd60e51b815260206004820152603660248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465206360448201527f6861696e2069642063616e6e6f74206265207a65726f000000000000000000006064820152608401620000cf565b6001600160a01b038316620001ce5760405162461bcd60e51b815260206004820152603960248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465207460448201527f6f6b656e2063616e6e6f742062652061646472657373283029000000000000006064820152608401620000cf565b60808490526001600160a01b0383811660a081905290861660c0526200020290601462000256602090811b62000dd217901c565b62000218856200041660201b62000ffb1760201c565b6040516020016200022b92919062000822565b604051602081830303815290604052600a90816200024a919062000756565b50505050505062000993565b6060600062000267836002620008ac565b62000274906002620008ce565b6001600160401b038111156200028e576200028e62000553565b6040519080825280601f01601f191660200182016040528015620002b9576020820181803683370190505b509050600360fc1b81600081518110620002d757620002d7620008e9565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110620003095762000309620008e9565b60200101906001600160f81b031916908160001a90535060006200032f846002620008ac565b6200033c906001620008ce565b90505b6001811115620003be576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620003745762000374620008e9565b1a60f81b8282815181106200038d576200038d620008e9565b60200101906001600160f81b031916908160001a90535060049490941c93620003b681620008ff565b90506200033f565b5083156200040f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620000cf565b9392505050565b6060816000036200043e5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156200046e5780620004558162000919565b9150620004669050600a836200094b565b915062000442565b6000816001600160401b038111156200048b576200048b62000553565b6040519080825280601f01601f191660200182016040528015620004b6576020820181803683370190505b5090505b84156200052e57620004ce60018362000962565b9150620004dd600a866200097c565b620004ea906030620008ce565b60f81b818381518110620005025762000502620008e9565b60200101906001600160f81b031916908160001a90535062000526600a866200094b565b9450620004ba565b949350505050565b80516001600160a01b03811681146200054e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620005865781810151838201526020016200056c565b8381111562000596576000848401525b50505050565b600082601f830112620005ae57600080fd5b81516001600160401b0380821115620005cb57620005cb62000553565b604051601f8301601f19908116603f01168101908282118183101715620005f657620005f662000553565b816040528381528660208588010111156200061057600080fd5b6200062384602083016020890162000569565b9695505050505050565b600080600080600060a086880312156200064657600080fd5b620006518662000536565b945060208601519350620006686040870162000536565b60608701519093506001600160401b03808211156200068657600080fd5b6200069489838a016200059c565b93506080880151915080821115620006ab57600080fd5b50620006ba888289016200059c565b9150509295509295909350565b600181811c90821680620006dc57607f821691505b602082108103620006fd57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200075157600081815260208120601f850160051c810160208610156200072c5750805b601f850160051c820191505b818110156200074d5782815560010162000738565b5050505b505050565b81516001600160401b0381111562000772576200077262000553565b6200078a81620007838454620006c7565b8462000703565b602080601f831160018114620007c25760008415620007a95750858301515b600019600386901b1c1916600185901b1785556200074d565b600085815260208120601f198616915b82811015620007f357888601518255948401946001909101908401620007d2565b5085821015620008125787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6832ba3432b932bab69d60b91b8152600083516200084881600985016020880162000569565b600160fe1b60099184019182015283516200086b81600a84016020880162000569565b712f746f6b656e5552493f75696e743235363d60701b600a9290910191820152601c01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620008c957620008c962000896565b500290565b60008219821115620008e457620008e462000896565b500190565b634e487b7160e01b600052603260045260246000fd5b60008162000911576200091162000896565b506000190190565b6000600182016200092e576200092e62000896565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826200095d576200095d62000935565b500490565b60008282101562000977576200097762000896565b500390565b6000826200098e576200098e62000935565b500690565b60805160a05160c05161242c620009d160003960008181610323015281816109f80152610ae6015260006102fc0152600061034a015261242c6000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c806395d89b41116100d8578063c87b56dd1161008c578063e78cea9211610066578063e78cea921461031e578063e951819614610345578063e985e9c51461036c57600080fd5b8063c87b56dd146102dc578063d547cfb7146102ef578063d6c0b2c4146102f757600080fd5b8063a1448194116100bd578063a1448194146102a3578063a22cb465146102b6578063b88d4fde146102c957600080fd5b806395d89b41146102885780639dc29fac1461029057600080fd5b806323b872dd1161013a5780634f6ccce7116101145780634f6ccce71461024f5780636352211e1461026257806370a082311461027557600080fd5b806323b872dd146102165780632f745c591461022957806342842e0e1461023c57600080fd5b8063081812fc1161016b578063081812fc146101c4578063095ea7b3146101ef57806318160ddd1461020457600080fd5b806301ffc9a71461018757806306fdde03146101af575b600080fd5b61019a610195366004611e6a565b6103a8565b60405190151581526020015b60405180910390f35b6101b7610457565b6040516101a69190611efd565b6101d76101d2366004611f10565b6104e9565b6040516001600160a01b0390911681526020016101a6565b6102026101fd366004611f45565b610594565b005b6008545b6040519081526020016101a6565b610202610224366004611f6f565b6106c5565b610208610237366004611f45565b61074c565b61020261024a366004611f6f565b6107f4565b61020861025d366004611f10565b61080f565b6101d7610270366004611f10565b6108b3565b610208610283366004611fab565b610944565b6101b76109de565b61020261029e366004611f45565b6109ed565b6102026102b1366004611f45565b610adb565b6102026102c4366004611fc6565b610bbe565b6102026102d7366004612031565b610bcd565b6101b76102ea366004611f10565b610c5b565b6101b7610d44565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6102087f000000000000000000000000000000000000000000000000000000000000000081565b61019a61037a36600461212b565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fe49bc7f8000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841682148061044057507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b8061044f575061044f84611130565b949350505050565b6060600080546104669061215e565b80601f01602080910402602001604051908101604052809291908181526020018280546104929061215e565b80156104df5780601f106104b4576101008083540402835291602001916104df565b820191906000526020600020905b8154815290600101906020018083116104c257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166105785760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061059f826108b3565b9050806001600160a01b0316836001600160a01b0316036106285760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161056f565b336001600160a01b03821614806106445750610644813361037a565b6106b65760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161056f565b6106c08383611186565b505050565b6106cf338261120c565b6107415760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b6106c0838383611313565b600061075783610944565b82106107cb5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e6473000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6106c083838360405180602001604052806000815250610bcd565b600061081a60085490565b821061088e5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e64730000000000000000000000000000000000000000606482015260840161056f565b600882815481106108a1576108a16121b1565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b03168061093e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e0000000000000000000000000000000000000000000000606482015260840161056f565b92915050565b60006001600160a01b0382166109c25760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f206164647265737300000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b031660009081526003602052604090205490565b6060600180546104669061215e565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a8b5760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610a9481611503565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca582604051610acf91815260200190565b60405180910390a25050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b795760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610b8382826115c2565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610acf91815260200190565b610bc93383836115dc565b5050565b610bd7338361120c565b610c495760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b610c55848484846116c8565b50505050565b6000818152600260205260409020546060906001600160a01b0316610ce85760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000606482015260840161056f565b6000610cf2611751565b90506000815111610d125760405180602001604052806000815250610d3d565b80610d1c84610ffb565b604051602001610d2d9291906121e0565b6040516020818303038152906040525b9392505050565b600a8054610d519061215e565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7d9061215e565b8015610dca5780601f10610d9f57610100808354040283529160200191610dca565b820191906000526020600020905b815481529060010190602001808311610dad57829003601f168201915b505050505081565b60606000610de183600261223e565b610dec90600261227b565b67ffffffffffffffff811115610e0457610e04612002565b6040519080825280601f01601f191660200182016040528015610e2e576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110610e6557610e656121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110610ec857610ec86121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000610f0484600261223e565b610f0f90600161227b565b90505b6001811115610fac577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110610f5057610f506121b1565b1a60f81b828281518110610f6657610f666121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93610fa581612293565b9050610f12565b508315610d3d5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161056f565b60608160000361103e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156110685780611052816122c8565b91506110619050600a8361232f565b9150611042565b60008167ffffffffffffffff81111561108357611083612002565b6040519080825280601f01601f1916602001820160405280156110ad576020820181803683370190505b5090505b841561044f576110c2600183612343565b91506110cf600a8661235a565b6110da90603061227b565b60f81b8183815181106110ef576110ef6121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611129600a8661232f565b94506110b1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d6300000000000000000000000000000000000000000000000000000000148061093e575061093e82611760565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841690811790915581906111d3826108b3565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166112965760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606482015260840161056f565b60006112a1836108b3565b9050806001600160a01b0316846001600160a01b031614806112e857506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b8061044f5750836001600160a01b0316611301846104e9565b6001600160a01b031614949350505050565b826001600160a01b0316611326826108b3565b6001600160a01b0316146113a25760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e6572000000000000000000000000000000000000000000000000000000606482015260840161056f565b6001600160a01b03821661141d5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161056f565b611428838383611843565b611433600082611186565b6001600160a01b038316600090815260036020526040812080546001929061145c908490612343565b90915550506001600160a01b038216600090815260036020526040812080546001929061148a90849061227b565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061150e826108b3565b905061151c81600084611843565b611527600083611186565b6001600160a01b0381166000908152600360205260408120805460019290611550908490612343565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b610bc98282604051806020016040528060008152506118fb565b816001600160a01b0316836001600160a01b03160361163d5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161056f565b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6116d3848484611313565b6116df84848484611984565b610c555760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b6060600a80546104669061215e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806117f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061093e57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461093e565b6001600160a01b03831661189e5761189981600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6118c1565b816001600160a01b0316836001600160a01b0316146118c1576118c18382611b43565b6001600160a01b0382166118d8576106c081611be0565b826001600160a01b0316826001600160a01b0316146106c0576106c08282611c8f565b6119058383611cd3565b6119126000848484611984565b6106c05760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b60006001600160a01b0384163b15611b38576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a02906119e190339089908890889060040161236e565b6020604051808303816000875af1925050508015611a3a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611a37918101906123aa565b60015b611aed573d808015611a68576040519150601f19603f3d011682016040523d82523d6000602084013e611a6d565b606091505b508051600003611ae55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a020000000000000000000000000000000000000000000000000000000014905061044f565b506001949350505050565b60006001611b5084610944565b611b5a9190612343565b600083815260076020526040902054909150808214611bad576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611bf290600190612343565b60008381526009602052604081205460088054939450909284908110611c1a57611c1a6121b1565b906000526020600020015490508060088381548110611c3b57611c3b6121b1565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611c7357611c736123c7565b6001900381819060005260206000200160009055905550505050565b6000611c9a83610944565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b038216611d295760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161056f565b6000818152600260205260409020546001600160a01b031615611d8e5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056f565b611d9a60008383611843565b6001600160a01b0382166000908152600360205260408120805460019290611dc390849061227b565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611e6757600080fd5b50565b600060208284031215611e7c57600080fd5b8135610d3d81611e39565b60005b83811015611ea2578181015183820152602001611e8a565b83811115610c555750506000910152565b60008151808452611ecb816020860160208601611e87565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d3d6020830184611eb3565b600060208284031215611f2257600080fd5b5035919050565b80356001600160a01b0381168114611f4057600080fd5b919050565b60008060408385031215611f5857600080fd5b611f6183611f29565b946020939093013593505050565b600080600060608486031215611f8457600080fd5b611f8d84611f29565b9250611f9b60208501611f29565b9150604084013590509250925092565b600060208284031215611fbd57600080fd5b610d3d82611f29565b60008060408385031215611fd957600080fd5b611fe283611f29565b915060208301358015158114611ff757600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561204757600080fd5b61205085611f29565b935061205e60208601611f29565b925060408501359150606085013567ffffffffffffffff8082111561208257600080fd5b818701915087601f83011261209657600080fd5b8135818111156120a8576120a8612002565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156120ee576120ee612002565b816040528281528a602084870101111561210757600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561213e57600080fd5b61214783611f29565b915061215560208401611f29565b90509250929050565b600181811c9082168061217257607f821691505b6020821081036121ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600083516121f2818460208801611e87565b835190830190612206818360208801611e87565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156122765761227661220f565b500290565b6000821982111561228e5761228e61220f565b500190565b6000816122a2576122a261220f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f9576122f961220f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261233e5761233e612300565b500490565b6000828210156123555761235561220f565b500390565b60008261236957612369612300565b500690565b60006001600160a01b038087168352808616602084015250836040830152608060608301526123a06080830184611eb3565b9695505050505050565b6000602082840312156123bc57600080fd5b8151610d3d81611e39565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220091cfc6e67938e5e9e61881af7ded22673b926104a9d05247aaec2f673e28e7364736f6c634300080f0033a2646970667358221220e0ec23cedfe5d74b2d927547b5882cd7e2b775e04cdebb66d2280c7da8786df664736f6c634300080f0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200006f5760003560e01c8063d97df6521162000056578063d97df65214620000cd578063e78cea92146200010a578063e9518196146200013257600080fd5b806354fd4d5014620000745780635572acae1462000096575b600080fd5b6200007e62000169565b6040516200008d9190620005dc565b60405180910390f35b620000bc620000a736600462000622565b60006020819052908152604090205460ff1681565b60405190151581526020016200008d565b620000e4620000de36600462000722565b62000214565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200008d565b620000e47f000000000000000000000000000000000000000000000000000000000000000081565b6200015a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016200008d565b6060620001967f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001c17f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001ec7f0000000000000000000000000000000000000000000000000000000000000000620003fa565b60405160200162000200939291906200079f565b604051602081830303815290604052905090565b600073ffffffffffffffffffffffffffffffffffffffff8416620002e5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a204c908201527f3120746f6b656e20616464726573732063616e6e6f742062652061646472657360648201527f7328302900000000000000000000000000000000000000000000000000000000608482015260a40160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008686866040516200033a906200054f565b6200034a9594939291906200081b565b604051809103906000f08015801562000367573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff8181166000818152602081815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590513381529394509188169290917fe72783bb8e0ca31286b85278da59684dd814df9762a52f0837f89edd1483b299910160405180910390a3949350505050565b6060816000036200043e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156200046e57806200045581620008ab565b9150620004669050600a8362000915565b915062000442565b60008167ffffffffffffffff8111156200048c576200048c62000640565b6040519080825280601f01601f191660200182016040528015620004b7576020820181803683370190505b5090505b84156200054757620004cf6001836200092c565b9150620004de600a8662000946565b620004eb9060306200095d565b60f81b81838151811062000503576200050362000978565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506200053f600a8662000915565b9450620004bb565b949350505050565b612dfd80620009a883390190565b60005b838110156200057a57818101518382015260200162000560565b838111156200058a576000848401525b50505050565b60008151808452620005aa8160208601602086016200055d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005f1602083018462000590565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061d57600080fd5b919050565b6000602082840312156200063557600080fd5b620005f182620005f8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200068157600080fd5b813567ffffffffffffffff808211156200069f576200069f62000640565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006e857620006e862000640565b816040528381528660208588010111156200070257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200073857600080fd5b6200074384620005f8565b9250602084013567ffffffffffffffff808211156200076157600080fd5b6200076f878388016200066f565b935060408601359150808211156200078657600080fd5b5062000795868287016200066f565b9150509250925092565b60008451620007b38184602089016200055d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551620007f1816001850160208a016200055d565b600192019182015283516200080e8160028401602088016200055d565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835286602084015280861660408401525060a060608301526200085c60a083018562000590565b828103608084015262000870818562000590565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620008df57620008df6200087c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082620009275762000927620008e6565b500490565b6000828210156200094157620009416200087c565b500390565b600082620009585762000958620008e6565b500690565b600082198211156200097357620009736200087c565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe60e06040523480156200001157600080fd5b5060405162002dfd38038062002dfd83398101604081905262000034916200062d565b8181600062000044838262000756565b50600162000053828262000756565b5050506001600160a01b038516620000d85760405162461bcd60e51b815260206004820152603360248201527f4f7074696d69736d4d696e7461626c654552433732313a20627269646765206360448201527f616e6e6f7420626520616464726573732830290000000000000000000000000060648201526084015b60405180910390fd5b83600003620001505760405162461bcd60e51b815260206004820152603660248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465206360448201527f6861696e2069642063616e6e6f74206265207a65726f000000000000000000006064820152608401620000cf565b6001600160a01b038316620001ce5760405162461bcd60e51b815260206004820152603960248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465207460448201527f6f6b656e2063616e6e6f742062652061646472657373283029000000000000006064820152608401620000cf565b60808490526001600160a01b0383811660a081905290861660c0526200020290601462000256602090811b62000dd217901c565b62000218856200041660201b62000ffb1760201c565b6040516020016200022b92919062000822565b604051602081830303815290604052600a90816200024a919062000756565b50505050505062000993565b6060600062000267836002620008ac565b62000274906002620008ce565b6001600160401b038111156200028e576200028e62000553565b6040519080825280601f01601f191660200182016040528015620002b9576020820181803683370190505b509050600360fc1b81600081518110620002d757620002d7620008e9565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110620003095762000309620008e9565b60200101906001600160f81b031916908160001a90535060006200032f846002620008ac565b6200033c906001620008ce565b90505b6001811115620003be576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620003745762000374620008e9565b1a60f81b8282815181106200038d576200038d620008e9565b60200101906001600160f81b031916908160001a90535060049490941c93620003b681620008ff565b90506200033f565b5083156200040f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620000cf565b9392505050565b6060816000036200043e5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156200046e5780620004558162000919565b9150620004669050600a836200094b565b915062000442565b6000816001600160401b038111156200048b576200048b62000553565b6040519080825280601f01601f191660200182016040528015620004b6576020820181803683370190505b5090505b84156200052e57620004ce60018362000962565b9150620004dd600a866200097c565b620004ea906030620008ce565b60f81b818381518110620005025762000502620008e9565b60200101906001600160f81b031916908160001a90535062000526600a866200094b565b9450620004ba565b949350505050565b80516001600160a01b03811681146200054e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620005865781810151838201526020016200056c565b8381111562000596576000848401525b50505050565b600082601f830112620005ae57600080fd5b81516001600160401b0380821115620005cb57620005cb62000553565b604051601f8301601f19908116603f01168101908282118183101715620005f657620005f662000553565b816040528381528660208588010111156200061057600080fd5b6200062384602083016020890162000569565b9695505050505050565b600080600080600060a086880312156200064657600080fd5b620006518662000536565b945060208601519350620006686040870162000536565b60608701519093506001600160401b03808211156200068657600080fd5b6200069489838a016200059c565b93506080880151915080821115620006ab57600080fd5b50620006ba888289016200059c565b9150509295509295909350565b600181811c90821680620006dc57607f821691505b602082108103620006fd57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200075157600081815260208120601f850160051c810160208610156200072c5750805b601f850160051c820191505b818110156200074d5782815560010162000738565b5050505b505050565b81516001600160401b0381111562000772576200077262000553565b6200078a81620007838454620006c7565b8462000703565b602080601f831160018114620007c25760008415620007a95750858301515b600019600386901b1c1916600185901b1785556200074d565b600085815260208120601f198616915b82811015620007f357888601518255948401946001909101908401620007d2565b5085821015620008125787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6832ba3432b932bab69d60b91b8152600083516200084881600985016020880162000569565b600160fe1b60099184019182015283516200086b81600a84016020880162000569565b712f746f6b656e5552493f75696e743235363d60701b600a9290910191820152601c01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620008c957620008c962000896565b500290565b60008219821115620008e457620008e462000896565b500190565b634e487b7160e01b600052603260045260246000fd5b60008162000911576200091162000896565b506000190190565b6000600182016200092e576200092e62000896565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826200095d576200095d62000935565b500490565b60008282101562000977576200097762000896565b500390565b6000826200098e576200098e62000935565b500690565b60805160a05160c05161242c620009d160003960008181610323015281816109f80152610ae6015260006102fc0152600061034a015261242c6000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c806395d89b41116100d8578063c87b56dd1161008c578063e78cea9211610066578063e78cea921461031e578063e951819614610345578063e985e9c51461036c57600080fd5b8063c87b56dd146102dc578063d547cfb7146102ef578063d6c0b2c4146102f757600080fd5b8063a1448194116100bd578063a1448194146102a3578063a22cb465146102b6578063b88d4fde146102c957600080fd5b806395d89b41146102885780639dc29fac1461029057600080fd5b806323b872dd1161013a5780634f6ccce7116101145780634f6ccce71461024f5780636352211e1461026257806370a082311461027557600080fd5b806323b872dd146102165780632f745c591461022957806342842e0e1461023c57600080fd5b8063081812fc1161016b578063081812fc146101c4578063095ea7b3146101ef57806318160ddd1461020457600080fd5b806301ffc9a71461018757806306fdde03146101af575b600080fd5b61019a610195366004611e6a565b6103a8565b60405190151581526020015b60405180910390f35b6101b7610457565b6040516101a69190611efd565b6101d76101d2366004611f10565b6104e9565b6040516001600160a01b0390911681526020016101a6565b6102026101fd366004611f45565b610594565b005b6008545b6040519081526020016101a6565b610202610224366004611f6f565b6106c5565b610208610237366004611f45565b61074c565b61020261024a366004611f6f565b6107f4565b61020861025d366004611f10565b61080f565b6101d7610270366004611f10565b6108b3565b610208610283366004611fab565b610944565b6101b76109de565b61020261029e366004611f45565b6109ed565b6102026102b1366004611f45565b610adb565b6102026102c4366004611fc6565b610bbe565b6102026102d7366004612031565b610bcd565b6101b76102ea366004611f10565b610c5b565b6101b7610d44565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6102087f000000000000000000000000000000000000000000000000000000000000000081565b61019a61037a36600461212b565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fe49bc7f8000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841682148061044057507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b8061044f575061044f84611130565b949350505050565b6060600080546104669061215e565b80601f01602080910402602001604051908101604052809291908181526020018280546104929061215e565b80156104df5780601f106104b4576101008083540402835291602001916104df565b820191906000526020600020905b8154815290600101906020018083116104c257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166105785760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061059f826108b3565b9050806001600160a01b0316836001600160a01b0316036106285760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161056f565b336001600160a01b03821614806106445750610644813361037a565b6106b65760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161056f565b6106c08383611186565b505050565b6106cf338261120c565b6107415760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b6106c0838383611313565b600061075783610944565b82106107cb5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e6473000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6106c083838360405180602001604052806000815250610bcd565b600061081a60085490565b821061088e5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e64730000000000000000000000000000000000000000606482015260840161056f565b600882815481106108a1576108a16121b1565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b03168061093e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e0000000000000000000000000000000000000000000000606482015260840161056f565b92915050565b60006001600160a01b0382166109c25760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f206164647265737300000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b031660009081526003602052604090205490565b6060600180546104669061215e565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a8b5760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610a9481611503565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca582604051610acf91815260200190565b60405180910390a25050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b795760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610b8382826115c2565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610acf91815260200190565b610bc93383836115dc565b5050565b610bd7338361120c565b610c495760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b610c55848484846116c8565b50505050565b6000818152600260205260409020546060906001600160a01b0316610ce85760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000606482015260840161056f565b6000610cf2611751565b90506000815111610d125760405180602001604052806000815250610d3d565b80610d1c84610ffb565b604051602001610d2d9291906121e0565b6040516020818303038152906040525b9392505050565b600a8054610d519061215e565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7d9061215e565b8015610dca5780601f10610d9f57610100808354040283529160200191610dca565b820191906000526020600020905b815481529060010190602001808311610dad57829003601f168201915b505050505081565b60606000610de183600261223e565b610dec90600261227b565b67ffffffffffffffff811115610e0457610e04612002565b6040519080825280601f01601f191660200182016040528015610e2e576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110610e6557610e656121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110610ec857610ec86121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000610f0484600261223e565b610f0f90600161227b565b90505b6001811115610fac577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110610f5057610f506121b1565b1a60f81b828281518110610f6657610f666121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93610fa581612293565b9050610f12565b508315610d3d5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161056f565b60608160000361103e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156110685780611052816122c8565b91506110619050600a8361232f565b9150611042565b60008167ffffffffffffffff81111561108357611083612002565b6040519080825280601f01601f1916602001820160405280156110ad576020820181803683370190505b5090505b841561044f576110c2600183612343565b91506110cf600a8661235a565b6110da90603061227b565b60f81b8183815181106110ef576110ef6121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611129600a8661232f565b94506110b1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d6300000000000000000000000000000000000000000000000000000000148061093e575061093e82611760565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841690811790915581906111d3826108b3565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166112965760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606482015260840161056f565b60006112a1836108b3565b9050806001600160a01b0316846001600160a01b031614806112e857506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b8061044f5750836001600160a01b0316611301846104e9565b6001600160a01b031614949350505050565b826001600160a01b0316611326826108b3565b6001600160a01b0316146113a25760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e6572000000000000000000000000000000000000000000000000000000606482015260840161056f565b6001600160a01b03821661141d5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161056f565b611428838383611843565b611433600082611186565b6001600160a01b038316600090815260036020526040812080546001929061145c908490612343565b90915550506001600160a01b038216600090815260036020526040812080546001929061148a90849061227b565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061150e826108b3565b905061151c81600084611843565b611527600083611186565b6001600160a01b0381166000908152600360205260408120805460019290611550908490612343565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b610bc98282604051806020016040528060008152506118fb565b816001600160a01b0316836001600160a01b03160361163d5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161056f565b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6116d3848484611313565b6116df84848484611984565b610c555760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b6060600a80546104669061215e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806117f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061093e57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461093e565b6001600160a01b03831661189e5761189981600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6118c1565b816001600160a01b0316836001600160a01b0316146118c1576118c18382611b43565b6001600160a01b0382166118d8576106c081611be0565b826001600160a01b0316826001600160a01b0316146106c0576106c08282611c8f565b6119058383611cd3565b6119126000848484611984565b6106c05760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b60006001600160a01b0384163b15611b38576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a02906119e190339089908890889060040161236e565b6020604051808303816000875af1925050508015611a3a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611a37918101906123aa565b60015b611aed573d808015611a68576040519150601f19603f3d011682016040523d82523d6000602084013e611a6d565b606091505b508051600003611ae55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a020000000000000000000000000000000000000000000000000000000014905061044f565b506001949350505050565b60006001611b5084610944565b611b5a9190612343565b600083815260076020526040902054909150808214611bad576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611bf290600190612343565b60008381526009602052604081205460088054939450909284908110611c1a57611c1a6121b1565b906000526020600020015490508060088381548110611c3b57611c3b6121b1565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611c7357611c736123c7565b6001900381819060005260206000200160009055905550505050565b6000611c9a83610944565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b038216611d295760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161056f565b6000818152600260205260409020546001600160a01b031615611d8e5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056f565b611d9a60008383611843565b6001600160a01b0382166000908152600360205260408120805460019290611dc390849061227b565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611e6757600080fd5b50565b600060208284031215611e7c57600080fd5b8135610d3d81611e39565b60005b83811015611ea2578181015183820152602001611e8a565b83811115610c555750506000910152565b60008151808452611ecb816020860160208601611e87565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d3d6020830184611eb3565b600060208284031215611f2257600080fd5b5035919050565b80356001600160a01b0381168114611f4057600080fd5b919050565b60008060408385031215611f5857600080fd5b611f6183611f29565b946020939093013593505050565b600080600060608486031215611f8457600080fd5b611f8d84611f29565b9250611f9b60208501611f29565b9150604084013590509250925092565b600060208284031215611fbd57600080fd5b610d3d82611f29565b60008060408385031215611fd957600080fd5b611fe283611f29565b915060208301358015158114611ff757600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561204757600080fd5b61205085611f29565b935061205e60208601611f29565b925060408501359150606085013567ffffffffffffffff8082111561208257600080fd5b818701915087601f83011261209657600080fd5b8135818111156120a8576120a8612002565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156120ee576120ee612002565b816040528281528a602084870101111561210757600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561213e57600080fd5b61214783611f29565b915061215560208401611f29565b90509250929050565b600181811c9082168061217257607f821691505b6020821081036121ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600083516121f2818460208801611e87565b835190830190612206818360208801611e87565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156122765761227661220f565b500290565b6000821982111561228e5761228e61220f565b500190565b6000816122a2576122a261220f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f9576122f961220f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261233e5761233e612300565b500490565b6000828210156123555761235561220f565b500390565b60008261236957612369612300565b500690565b60006001600160a01b038087168352808616602084015250836040830152608060608301526123a06080830184611eb3565b9695505050505050565b6000602082840312156123bc57600080fd5b8151610d3d81611e39565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220091cfc6e67938e5e9e61881af7ded22673b926104a9d05247aaec2f673e28e7364736f6c634300080f0033a2646970667358221220e0ec23cedfe5d74b2d927547b5882cd7e2b775e04cdebb66d2280c7da8786df664736f6c634300080f0033", + "devdoc": { + "events": { + "OptimismMintableERC721Created(address,address,address)": { + "params": { + "deployer": "Address of the initiator of the deployment", + "localToken": "Address of the token on the this domain.", + "remoteToken": "Address of the token on the remote domain." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "custom:semver": "1.0.0", + "params": { + "_bridge": "Address of the ERC721 bridge on this network." + } + }, + "createOptimismMintableERC721(address,string,string)": { + "params": { + "_name": "ERC721 name.", + "_remoteToken": "Address of the corresponding token on the other domain.", + "_symbol": "ERC721 symbol." + } + }, + "version()": { + "returns": { + "_0": "Semver contract version as a string." + } + } + }, + "title": "OptimismMintableERC721Factory", + "version": 1 + }, + "userdoc": { + "events": { + "OptimismMintableERC721Created(address,address,address)": { + "notice": "Emitted whenever a new OptimismMintableERC721 contract is created." + } + }, + "kind": "user", + "methods": { + "bridge()": { + "notice": "Address of the ERC721 bridge on this network." + }, + "createOptimismMintableERC721(address,string,string)": { + "notice": "Creates an instance of the standard ERC721." + }, + "isOptimismMintableERC721(address)": { + "notice": "Tracks addresses created by this factory." + }, + "remoteChainId()": { + "notice": "Chain ID for the remote network." + }, + "version()": { + "notice": "Returns the full semver contract version." + } + }, + "notice": "Factory contract for creating OptimismMintableERC721 contracts.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 8543, + "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", + "label": "isOptimismMintableERC721", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-goerli/OptimismMintableERC721FactoryProxy.json b/packages/contracts-periphery/deployments/optimism-goerli/OptimismMintableERC721FactoryProxy.json new file mode 100644 index 0000000000000..69482dda23fb7 --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism-goerli/OptimismMintableERC721FactoryProxy.json @@ -0,0 +1,257 @@ +{ + "address": "0x83F019dE99dB0cA483A5f2fC7053D3EA57BdE06D", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x12ed035f890442d691aa03f20b5fff5e2e599af0cabb84978efc7af59df050bb", + "receipt": { + "to": null, + "from": "0x5c679a57e018F5F146838138d3E032Ef4913D551", + "contractAddress": "0x83F019dE99dB0cA483A5f2fC7053D3EA57BdE06D", + "transactionIndex": 0, + "gasUsed": "532674", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000040000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc8b5cf8db3d9d3bc1045e53fd6d1e075a720e4aa76b3593e63478baf60d37356", + "transactionHash": "0x12ed035f890442d691aa03f20b5fff5e2e599af0cabb84978efc7af59df050bb", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 1563185, + "transactionHash": "0x12ed035f890442d691aa03f20b5fff5e2e599af0cabb84978efc7af59df050bb", + "address": "0x83F019dE99dB0cA483A5f2fC7053D3EA57BdE06D", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000005c679a57e018f5f146838138d3e032ef4913d551", + "logIndex": 0, + "blockHash": "0xc8b5cf8db3d9d3bc1045e53fd6d1e075a720e4aa76b3593e63478baf60d37356" + } + ], + "blockNumber": 1563185, + "cumulativeGasUsed": "532674", + "status": 1, + "byzantium": true + }, + "args": [ + "0x5c679a57e018F5F146838138d3E032Ef4913D551" + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"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\"}}},\"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.\"}}},\"title\":\"Proxy\",\"version\":1},\"userdoc\":{\"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.\"}},\"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.\"},\"implementation()\":{\"notice\":\"Queries the implementation address.\"},\"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.\"}},\"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.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title Proxy\\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\\n * if the caller is address(0), meaning that the call originated from an off-chain\\n * simulation.\\n */\\ncontract Proxy {\\n /**\\n * @notice The storage slot that holds the address of the implementation.\\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n */\\n bytes32 internal constant IMPLEMENTATION_KEY =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @notice The storage slot that holds the address of the owner.\\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n */\\n bytes32 internal constant OWNER_KEY =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @notice An event that is emitted each time the implementation is changed. This event is part\\n * of the EIP-1967 specification.\\n *\\n * @param implementation The address of the implementation contract\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\\n * EIP-1967 specification.\\n *\\n * @param previousAdmin The previous owner of the contract\\n * @param newAdmin The new owner of the contract\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\\n * eth_call to interact with this proxy without needing to use low-level storage\\n * inspection. We assume that nobody is able to trigger calls from address(0) during\\n * normal EVM execution.\\n */\\n modifier proxyCallIfNotAdmin() {\\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\\n _;\\n } else {\\n // This WILL halt the call frame on completion.\\n _doProxyCall();\\n }\\n }\\n\\n /**\\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\\n * EIP-1967 admin storage slot so that accidental storage collision with the\\n * implementation is not possible.\\n *\\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\\n * transparent proxy interface.\\n */\\n constructor(address _admin) {\\n _changeAdmin(_admin);\\n }\\n\\n // slither-disable-next-line locked-ether\\n receive() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n // slither-disable-next-line locked-ether\\n fallback() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n /**\\n * @notice Set the implementation contract address. The code at the given address will execute\\n * when this contract is called.\\n *\\n * @param _implementation Address of the implementation contract.\\n */\\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\\n _setImplementation(_implementation);\\n }\\n\\n /**\\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\\n * atomic execution of initialization-based upgrades.\\n *\\n * @param _implementation Address of the implementation contract.\\n * @param _data Calldata to delegatecall the new implementation with.\\n */\\n function upgradeToAndCall(address _implementation, bytes calldata _data)\\n external\\n payable\\n proxyCallIfNotAdmin\\n returns (bytes memory)\\n {\\n _setImplementation(_implementation);\\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\\n require(success, \\\"Proxy: delegatecall to new implementation contract failed\\\");\\n return returndata;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\\n _changeAdmin(_admin);\\n }\\n\\n /**\\n * @notice Gets the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function admin() external proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() external proxyCallIfNotAdmin returns (address) {\\n return _getImplementation();\\n }\\n\\n /**\\n * @notice Sets the implementation address.\\n *\\n * @param _implementation New implementation address.\\n */\\n function _setImplementation(address _implementation) internal {\\n assembly {\\n sstore(IMPLEMENTATION_KEY, _implementation)\\n }\\n emit Upgraded(_implementation);\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function _changeAdmin(address _admin) internal {\\n address previous = _getAdmin();\\n assembly {\\n sstore(OWNER_KEY, _admin)\\n }\\n emit AdminChanged(previous, _admin);\\n }\\n\\n /**\\n * @notice Performs the proxy call via a delegatecall.\\n */\\n function _doProxyCall() internal {\\n address impl = _getImplementation();\\n require(impl != address(0), \\\"Proxy: implementation not initialized\\\");\\n\\n assembly {\\n // Copy calldata into memory at 0x0....calldatasize.\\n calldatacopy(0x0, 0x0, calldatasize())\\n\\n // Perform the delegatecall, make sure to pass all available gas.\\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\\n\\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\\n // overwrite the calldata that we just copied into memory but that doesn't really\\n // matter because we'll be returning in a second anyway.\\n returndatacopy(0x0, 0x0, returndatasize())\\n\\n // Success == 0 means a revert. We'll revert too and pass the data up.\\n if iszero(success) {\\n revert(0x0, returndatasize())\\n }\\n\\n // Otherwise we'll just return and pass the data up.\\n return(0x0, returndatasize())\\n }\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n address impl;\\n assembly {\\n impl := sload(IMPLEMENTATION_KEY)\\n }\\n return impl;\\n }\\n\\n /**\\n * @notice Queries the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function _getAdmin() internal view returns (address) {\\n address owner;\\n assembly {\\n owner := sload(OWNER_KEY)\\n }\\n return owner;\\n }\\n}\\n\",\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5060405161094138038061094183398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206109218339815191525490565b600080516020610921833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610830806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033", + "devdoc": { + "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" + } + } + }, + "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." + } + } + }, + "title": "Proxy", + "version": 1 + }, + "userdoc": { + "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." + } + }, + "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." + }, + "implementation()": { + "notice": "Queries the implementation address." + }, + "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." + } + }, + "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.", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-goerli/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json b/packages/contracts-periphery/deployments/optimism-goerli/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json new file mode 100644 index 0000000000000..91d5f99068af8 --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism-goerli/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json @@ -0,0 +1,173 @@ +{ + "language": "Solidity", + "sources": { + "contracts/L1/L1ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L1ERC721Bridge\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as an escrow for ERC721 tokens deposited into L2.\n */\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\n * by ID was deposited for a given L2 token.\n */\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\n * execute any code on L2 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L1ERC721Bridge: local token cannot be self\");\n\n // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\n require(\n deposits[_localToken][_remoteToken][_tokenId] == true,\n \"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\"\n );\n\n // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\n // Bridge.\n deposits[_localToken][_remoteToken][_tokenId] = false;\n\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\n // withdrawer.\n IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\n bytes memory message = abi.encodeWithSelector(\n L2ERC721Bridge.finalizeBridgeERC721.selector,\n _remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Lock token into bridge\n deposits[_localToken][_remoteToken][_tokenId] = true;\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\n\n // Send calldata into L2\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "contracts/universal/op-erc721/ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n CrossDomainMessenger\n} from \"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title ERC721Bridge\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\n */\nabstract contract ERC721Bridge {\n /**\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable messenger;\n\n /**\n * @notice Address of the bridge on the other network.\n */\n address public immutable otherBridge;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[49] private __gap;\n\n /**\n * @notice Ensures that the caller is a cross-chain message from the other bridge.\n */\n modifier onlyOtherBridge() {\n require(\n msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\n \"ERC721Bridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge) {\n require(_messenger != address(0), \"ERC721Bridge: messenger cannot be address(0)\");\n require(_otherBridge != address(0), \"ERC721Bridge: other bridge cannot be address(0)\");\n\n messenger = CrossDomainMessenger(_messenger);\n otherBridge = _otherBridge;\n }\n\n /**\n * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\n * this function can only be called by EOAs. Smart contract wallets should use the\n * `bridgeERC721To` function after ensuring that the recipient address on the remote\n * chain exists. Also note that the current owner of the token on this chain must\n * approve this contract to operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721(\n address _localToken,\n address _remoteToken,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n // Modifier requiring sender to be EOA. This prevents against a user error that would occur\n // if the sender is a smart contract wallet that has a different address on the remote chain\n // (or doesn't have an address on the remote chain at all). The user would fail to receive\n // the NFT if they use this function because it sends the NFT to the same address as the\n // caller. This check could be bypassed by a malicious contract via initcode, but it takes\n // care of the user error we want to avoid.\n require(!Address.isContract(msg.sender), \"ERC721Bridge: account is not externally owned\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\n * that the current owner of the token on this chain must approve this contract to\n * operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n require(_to != address(0), \"ERC721Bridge: nft recipient cannot be address(0)\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Internal function for initiating a token bridge to the other domain.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _from Address of the sender on this domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other domain. Data supplied here will\n * not be used to execute any code on the other domain and is only emitted\n * as extra data for the convenience of off-chain tooling.\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal virtual;\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "contracts/L2/L2ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/op-erc721/IOptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L2ERC721Bridge\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\n * This contract also acts as a burner for tokens being withdrawn.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n */\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\n * execute any code on L1 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L2ERC721Bridge: local token cannot be self\");\n\n // Note that supportsInterface makes a callback to the _localToken address which is user\n // provided.\n require(\n ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\n \"L2ERC721Bridge: local token interface is not compliant\"\n );\n\n require(\n _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\n \"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\"\n );\n\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\n // on L2. Note that safeMint makes a callback to the _to address which is user provided.\n IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Check that the withdrawal is being initiated by the NFT owner\n require(\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\n \"Withdrawal is not being initiated by NFT owner\"\n );\n\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\n // slither-disable-next-line reentrancy-events\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\n require(\n remoteToken == _remoteToken,\n \"L2ERC721Bridge: remote token does not match given value\"\n );\n\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\n // usage\n // slither-disable-next-line reentrancy-events\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\n\n bytes memory message = abi.encodeWithSelector(\n L1ERC721Bridge.finalizeBridgeERC721.selector,\n remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Send message to L1 bridge\n // slither-disable-next-line reentrancy-events\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\n\n/**\n * @title Semver\n * @notice Semver is a simple contract for managing contract versions.\n */\ncontract Semver {\n /**\n * @notice Contract version number (major).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable PATCH_VERSION;\n\n /**\n * @param _major Version number (major).\n * @param _minor Version number (minor).\n * @param _patch Version number (patch).\n */\n constructor(\n uint256 _major,\n uint256 _minor,\n uint256 _patch\n ) {\n MAJOR_VERSION = _major;\n MINOR_VERSION = _minor;\n PATCH_VERSION = _patch;\n }\n\n /**\n * @notice Returns the full semver contract version.\n *\n * @return Semver contract version as a string.\n */\n function version() public view returns (string memory) {\n return\n string(\n abi.encodePacked(\n Strings.toString(MAJOR_VERSION),\n \".\",\n Strings.toString(MINOR_VERSION),\n \".\",\n Strings.toString(PATCH_VERSION)\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n PausableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {\n ReentrancyGuardUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * libAddressManager variable used to exist. Must be the first contract in the inheritance\n * tree of the CrossDomainMessenger\n */\ncontract CrossDomainMessengerLegacySpacer {\n /**\n * @custom:legacy\n * @custom:spacer libAddressManager\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n}\n\n/**\n * @custom:upgradeable\n * @title CrossDomainMessenger\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\n * cross-chain messenger contracts. It's designed to be a universal interface that only\n * needs to be extended slightly to provide low-level message passing functionality on each\n * chain it's deployed on. Currently only designed for message passing between two paired\n * chains and does not support one-to-many interactions.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer,\n OwnableUpgradeable,\n PausableUpgradeable,\n ReentrancyGuardUpgradeable\n{\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Constant overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\n\n /**\n * @notice Numerator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\n\n /**\n * @notice Denominator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\n\n /**\n * @notice Extra gas added to base gas for each byte of calldata in a message.\n */\n uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Minimum amount of gas required to relay a message.\n */\n uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\n\n /**\n * @notice Amount of gas held in reserve to guarantee that relay execution completes.\n */\n uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\n\n /**\n * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\n * because performing an SSTORE on a non-zero value is significantly cheaper than on a\n * zero value.\n */\n address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable otherMessenger;\n\n /**\n * @custom:legacy\n * @custom:spacer blockedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_201_0_32;\n\n /**\n * @custom:legacy\n * @custom:spacer relayedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_202_0_32;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it has successfully been relayed on this chain, and\n * can therefore not be relayed again.\n */\n mapping(bytes32 => bool) public successfulMessages;\n\n /**\n * @notice Address of the sender of the currently executing message on the other chain. If the\n * value of this variable is the default value (0x00000000...dead) then no message is\n * currently being executed. Use the xDomainMessageSender getter which will throw an\n * error if this is the case.\n */\n address internal xDomainMsgSender;\n\n /**\n * @notice Nonce for the next message to be sent, without the message version applied. Use the\n * messageNonce getter which will insert the message version into the nonce to give you\n * the actual nonce to be used for the message.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it failed to be relayed on this chain at least once.\n * If a message is successfully relayed on the first attempt, then it will only be\n * present within the successfulMessages mapping.\n */\n mapping(bytes32 => bool) public receivedMessages;\n\n /**\n * @notice Reserve extra slots in the storage layout for future upgrades.\n * A gap size of 41 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[42] private __gap;\n\n /**\n * @notice Emitted whenever a message is sent to the other chain.\n *\n * @param target Address of the recipient of the message.\n * @param sender Address of the sender of the message.\n * @param message Message to trigger the recipient address with.\n * @param messageNonce Unique nonce attached to the message.\n * @param gasLimit Minimum gas limit that the message can be executed with.\n */\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n /**\n * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\n * SentMessage event without breaking the ABI of this contract, this is good enough.\n *\n * @param sender Address of the sender of the message.\n * @param value ETH value sent along with the message to the recipient.\n */\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n /**\n * @notice Emitted whenever a message is successfully relayed on this chain.\n *\n * @param msgHash Hash of the message that was relayed.\n */\n event RelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @notice Emitted whenever a message fails to be relayed on this chain.\n *\n * @param msgHash Hash of the message that failed to be relayed.\n */\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @param _otherMessenger Address of the messenger on the paired chain.\n */\n constructor(address _otherMessenger) {\n otherMessenger = _otherMessenger;\n }\n\n /**\n * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\n * security mechanism just in case. Owner should be the same as the upgrade wallet to\n * maintain the security model of the system as a whole.\n */\n function pause() external onlyOwner {\n _pause();\n }\n\n /**\n * @notice Allows the owner of this contract to resume message relaying once paused.\n */\n function unpause() external onlyOwner {\n _unpause();\n }\n\n /**\n * @notice Sends a message to some target address on the other chain. Note that if the call\n * always reverts, then the message will be unrelayable, and any ETH sent will be\n * permanently locked. The same will occur if the target on the other chain is\n * considered unsafe (see the _isUnsafeTarget() function).\n *\n * @param _target Target contract or wallet address.\n * @param _message Message to trigger the target address with.\n * @param _minGasLimit Minimum gas limit that the message can be executed with.\n */\n function sendMessage(\n address _target,\n bytes calldata _message,\n uint32 _minGasLimit\n ) external payable {\n // Triggers a message to the other messenger. Note that the amount of gas provided to the\n // message is the amount of gas requested by the user PLUS the base gas value. We want to\n // guarantee the property that the call to the target contract will always have at least\n // the minimum gas limit specified by the user.\n _sendMessage(\n otherMessenger,\n baseGas(_message, _minGasLimit),\n msg.value,\n abi.encodeWithSelector(\n this.relayMessage.selector,\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _minGasLimit,\n _message\n )\n );\n\n emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\n emit SentMessageExtension1(msg.sender, msg.value);\n\n unchecked {\n ++msgNonce;\n }\n }\n\n /**\n * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\n * be executed via cross-chain call from the other messenger OR if the message was\n * already received once and is currently being replayed.\n *\n * @param _nonce Nonce of the message being relayed.\n * @param _sender Address of the user who sent the message.\n * @param _target Address that the message is targeted at.\n * @param _value ETH value to send with the message.\n * @param _minGasLimit Minimum amount of gas that the message can be executed with.\n * @param _message Message to send to the target.\n */\n function relayMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _minGasLimit,\n bytes calldata _message\n ) external payable nonReentrant whenNotPaused {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n\n // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\n // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\n // to the value or minGasLimit fields, which can create unexpected issues for end-users.\n require(\n version == 1,\n \"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\"\n );\n\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n if (_isOtherMessenger()) {\n // This property should always hold when the message is first submitted (as opposed to\n // being replayed).\n assert(msg.value == _value);\n } else {\n require(\n msg.value == 0,\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n\n require(\n receivedMessages[versionedHash],\n \"CrossDomainMessenger: message cannot be replayed\"\n );\n }\n\n require(\n _isUnsafeTarget(_target) == false,\n \"CrossDomainMessenger: cannot send message to blocked system address\"\n );\n\n require(\n successfulMessages[versionedHash] == false,\n \"CrossDomainMessenger: message has already been relayed\"\n );\n\n require(\n gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\n \"CrossDomainMessenger: insufficient gas to relay message\"\n );\n\n xDomainMsgSender = _sender;\n bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n\n if (success == true) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n receivedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n }\n }\n\n /**\n * @notice Retrieves the address of the contract or wallet that initiated the currently\n * executing message on the other chain. Will throw an error if there is no message\n * currently being executed. Allows the recipient of a call to see who triggered it.\n *\n * @return Address of the sender of the currently executing message on the other chain.\n */\n function xDomainMessageSender() external view returns (address) {\n require(\n xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\n \"CrossDomainMessenger: xDomainMessageSender is not set\"\n );\n\n return xDomainMsgSender;\n }\n\n /**\n * @notice Retrieves the next message nonce. Message version will be added to the upper two\n * bytes of the message nonce. Message version allows us to treat messages as having\n * different structures.\n *\n * @return Nonce of the next message to be sent, with added message version.\n */\n function messageNonce() public view returns (uint256) {\n return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\n }\n\n /**\n * @notice Computes the amount of gas required to guarantee that a given message will be\n * received on the other chain without running out of gas. Guaranteeing that a message\n * will not run out of gas is important because this ensures that a message can always\n * be replayed on the other chain if it fails to execute completely.\n *\n * @param _message Message to compute the amount of required gas for.\n * @param _minGasLimit Minimum desired gas limit when message goes to target.\n *\n * @return Amount of gas required to guarantee message receipt.\n */\n function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\n return\n // Dynamic overhead\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\n // Constant overhead\n MIN_GAS_CONSTANT_OVERHEAD;\n }\n\n /**\n * @notice Intializer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __CrossDomainMessenger_init() internal onlyInitializing {\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n __ReentrancyGuard_init_unchained();\n }\n\n /**\n * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @param _to Recipient of the message on the other chain.\n * @param _gasLimit Minimum gas limit the message can be executed with.\n * @param _value Amount of ETH to send with the message.\n * @param _data Message data.\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal virtual;\n\n /**\n * @notice Checks whether the message is coming from the other messenger. Implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @return Whether the message is coming from the other messenger.\n */\n function _isOtherMessenger() internal view virtual returns (bool);\n\n /**\n * @notice Checks whether a given call target is a system address that could cause the\n * messenger to peform an unsafe action. This is NOT a mechanism for blocking user\n * addresses. This is ONLY used to prevent the execution of messages to specific\n * system addresses that could cause security issues, e.g., having the\n * CrossDomainMessenger send messages to itself.\n *\n * @param _target Address of the contract to check.\n *\n * @return Whether or not the address is an unsafe system address.\n */\n function _isUnsafeTarget(address _target) internal view virtual returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title SafeCall\n * @notice Perform low level safe calls\n */\nlibrary SafeCall {\n /**\n * @notice Perform a low level call without copying any returndata\n *\n * @param _target Address to call\n * @param _gas Amount of gas to pass to the call\n * @param _value Amount of value to pass to the call\n * @param _calldata Calldata to pass to the call\n */\n function call(\n address _target,\n uint256 _gas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n assembly {\n _success := call(\n _gas, // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Encoding } from \"./Encoding.sol\";\n\n/**\n * @title Hashing\n * @notice Hashing handles Optimism's various different hashing schemes.\n */\nlibrary Hashing {\n /**\n * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\n * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\n * system.\n *\n * @param _tx User deposit transaction to hash.\n *\n * @return Hash of the RLP encoded L2 deposit transaction.\n */\n function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return keccak256(Encoding.encodeDepositTransaction(_tx));\n }\n\n /**\n * @notice Computes the deposit transaction's \"source hash\", a value that guarantees the hash\n * of the L2 transaction that corresponds to a deposit is unique and is\n * deterministically generated from L1 transaction data.\n *\n * @param _l1BlockHash Hash of the L1 block where the deposit was included.\n * @param _logIndex The index of the log that created the deposit transaction.\n *\n * @return Hash of the deposit transaction's \"source hash\".\n */\n function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\n internal\n pure\n returns (bytes32)\n {\n bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\n return keccak256(abi.encode(bytes32(0), depositId));\n }\n\n /**\n * @notice Hashes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n if (version == 0) {\n return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Hashing: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes32) {\n return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\n }\n\n /**\n * @notice Hashes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n return\n keccak256(\n Encoding.encodeCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n )\n );\n }\n\n /**\n * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\n *\n * @param _tx Withdrawal transaction to hash.\n *\n * @return Hashed withdrawal transaction.\n */\n function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\n );\n }\n\n /**\n * @notice Hashes the various elements of an output root proof into an output root hash which\n * can be used to check if the proof is valid.\n *\n * @param _outputRootProof Output root proof which should hash to an output root.\n *\n * @return Hashed output root proof.\n */\n function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(\n _outputRootProof.version,\n _outputRootProof.stateRoot,\n _outputRootProof.messagePasserStorageRoot,\n _outputRootProof.latestBlockhash\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Hashing } from \"./Hashing.sol\";\nimport { RLPWriter } from \"./rlp/RLPWriter.sol\";\n\n/**\n * @title Encoding\n * @notice Encoding handles Optimism's various different encoding schemes.\n */\nlibrary Encoding {\n /**\n * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\n * to the L2 system. Useful for searching for a deposit in the L2 system. The\n * transaction is prefixed with 0x7e to identify its EIP-2718 type.\n *\n * @param _tx User deposit transaction to encode.\n *\n * @return RLP encoded L2 deposit transaction.\n */\n function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes memory)\n {\n bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\n bytes[] memory raw = new bytes[](8);\n raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\n raw[1] = RLPWriter.writeAddress(_tx.from);\n raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\"\") : RLPWriter.writeAddress(_tx.to);\n raw[3] = RLPWriter.writeUint(_tx.mint);\n raw[4] = RLPWriter.writeUint(_tx.value);\n raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\n raw[6] = RLPWriter.writeBool(false);\n raw[7] = RLPWriter.writeBytes(_tx.data);\n return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\n }\n\n /**\n * @notice Encodes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n (, uint16 version) = decodeVersionedNonce(_nonce);\n if (version == 0) {\n return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Encoding: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _data,\n _nonce\n );\n }\n\n /**\n * @notice Encodes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(uint256,address,address,uint256,uint256,bytes)\",\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n }\n\n /**\n * @notice Adds a version number into the first two bytes of a message nonce.\n *\n * @param _nonce Message nonce to encode into.\n * @param _version Version number to encode into the message nonce.\n *\n * @return Message nonce with version encoded into the first two bytes.\n */\n function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\n uint256 nonce;\n assembly {\n nonce := or(shl(240, _version), _nonce)\n }\n return nonce;\n }\n\n /**\n * @notice Pulls the version out of a version-encoded nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n *\n * @return Nonce without encoded version.\n * @return Version of the message.\n */\n function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\n uint240 nonce;\n uint16 version;\n assembly {\n nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n version := shr(240, _nonce)\n }\n return (nonce, version);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Types\n * @notice Contains various types used throughout the Optimism contract system.\n */\nlibrary Types {\n /**\n * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\n * timestamp that the output root is posted. This timestamp is used to verify that the\n * finalization period has passed since the output root was submitted.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint256 timestamp;\n }\n\n /**\n * @notice Struct representing the elements that are hashed together to generate an output root\n * which itself represents a snapshot of the L2 state.\n */\n struct OutputRootProof {\n bytes32 version;\n bytes32 stateRoot;\n bytes32 messagePasserStorageRoot;\n bytes32 latestBlockhash;\n }\n\n /**\n * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\n * user (as opposed to a system deposit transaction generated by the system).\n */\n struct UserDepositTransaction {\n address from;\n address to;\n bool isCreation;\n uint256 value;\n uint256 mint;\n uint64 gasLimit;\n bytes data;\n bytes32 l1BlockHash;\n uint256 logIndex;\n }\n\n /**\n * @notice Struct representing a withdrawal transaction.\n */\n struct WithdrawalTransaction {\n uint256 nonce;\n address sender;\n address target;\n uint256 value;\n uint256 gasLimit;\n bytes data;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\n * @title RLPWriter\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\n * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\n * modifications to improve legibility.\n */\nlibrary RLPWriter {\n /**\n * @notice RLP encodes a byte string.\n *\n * @param _in The byte string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_in.length == 1 && uint8(_in[0]) < 128) {\n encoded = _in;\n } else {\n encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\n }\n\n return encoded;\n }\n\n /**\n * @notice RLP encodes a list of RLP encoded byte byte strings.\n *\n * @param _in The list of RLP encoded byte strings.\n *\n * @return The RLP encoded list of items in bytes.\n */\n function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\n bytes memory list = _flatten(_in);\n return abi.encodePacked(_writeLength(list.length, 192), list);\n }\n\n /**\n * @notice RLP encodes a string.\n *\n * @param _in The string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeString(string memory _in) internal pure returns (bytes memory) {\n return writeBytes(bytes(_in));\n }\n\n /**\n * @notice RLP encodes an address.\n *\n * @param _in The address to encode.\n *\n * @return The RLP encoded address in bytes.\n */\n function writeAddress(address _in) internal pure returns (bytes memory) {\n return writeBytes(abi.encodePacked(_in));\n }\n\n /**\n * @notice RLP encodes a uint.\n *\n * @param _in The uint256 to encode.\n *\n * @return The RLP encoded uint256 in bytes.\n */\n function writeUint(uint256 _in) internal pure returns (bytes memory) {\n return writeBytes(_toBinary(_in));\n }\n\n /**\n * @notice RLP encodes a bool.\n *\n * @param _in The bool to encode.\n *\n * @return The RLP encoded bool in bytes.\n */\n function writeBool(bool _in) internal pure returns (bytes memory) {\n bytes memory encoded = new bytes(1);\n encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n return encoded;\n }\n\n /**\n * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\n *\n * @param _len The length of the string or the payload.\n * @param _offset 128 if item is string, 192 if item is list.\n *\n * @return RLP encoded bytes.\n */\n function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_len < 56) {\n encoded = new bytes(1);\n encoded[0] = bytes1(uint8(_len) + uint8(_offset));\n } else {\n uint256 lenLen;\n uint256 i = 1;\n while (_len / i != 0) {\n lenLen++;\n i *= 256;\n }\n\n encoded = new bytes(lenLen + 1);\n encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\n for (i = 1; i <= lenLen; i++) {\n encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\n }\n }\n\n return encoded;\n }\n\n /**\n * @notice Encode integer in big endian binary form with no leading zeroes.\n *\n * @param _x The integer to encode.\n *\n * @return RLP encoded bytes.\n */\n function _toBinary(uint256 _x) private pure returns (bytes memory) {\n bytes memory b = abi.encodePacked(_x);\n\n uint256 i = 0;\n for (; i < 32; i++) {\n if (b[i] != 0) {\n break;\n }\n }\n\n bytes memory res = new bytes(32 - i);\n for (uint256 j = 0; j < res.length; j++) {\n res[j] = b[i++];\n }\n\n return res;\n }\n\n /**\n * @custom:attribution https://github.com/Arachnid/solidity-stringutils\n * @notice Copies a piece of memory to another location.\n *\n * @param _dest Destination location.\n * @param _src Source location.\n * @param _len Length of memory to copy.\n */\n function _memcpy(\n uint256 _dest,\n uint256 _src,\n uint256 _len\n ) private pure {\n uint256 dest = _dest;\n uint256 src = _src;\n uint256 len = _len;\n\n for (; len >= 32; len -= 32) {\n assembly {\n mstore(dest, mload(src))\n }\n dest += 32;\n src += 32;\n }\n\n uint256 mask;\n unchecked {\n mask = 256**(32 - len) - 1;\n }\n assembly {\n let srcpart := and(mload(src), not(mask))\n let destpart := and(mload(dest), mask)\n mstore(dest, or(destpart, srcpart))\n }\n }\n\n /**\n * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\n * @notice Flattens a list of byte strings into one byte string.\n *\n * @param _list List of byte strings to flatten.\n *\n * @return The flattened byte string.\n */\n function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\n if (_list.length == 0) {\n return new bytes(0);\n }\n\n uint256 len;\n uint256 i = 0;\n for (; i < _list.length; i++) {\n len += _list[i].length;\n }\n\n bytes memory flattened = new bytes(len);\n uint256 flattenedPtr;\n assembly {\n flattenedPtr := add(flattened, 0x20)\n }\n\n for (i = 0; i < _list.length; i++) {\n bytes memory item = _list[i];\n\n uint256 listPtr;\n assembly {\n listPtr := add(item, 0x20)\n }\n\n _memcpy(flattenedPtr, listPtr, item.length);\n flattenedPtr += _list[i].length;\n }\n\n return flattened;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" + }, + "contracts/universal/op-erc721/IOptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n IERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\";\n\n/**\n * @title IOptimismMintableERC721\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\n */\ninterface IOptimismMintableERC721 is IERC721Enumerable {\n /**\n * @notice Emitted when a token is minted.\n *\n * @param account Address of the account the token was minted to.\n * @param tokenId Token ID of the minted token.\n */\n event Mint(address indexed account, uint256 tokenId);\n\n /**\n * @notice Emitted when a token is burned.\n *\n * @param account Address of the account the token was burned from.\n * @param tokenId Token ID of the burned token.\n */\n event Burn(address indexed account, uint256 tokenId);\n\n /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function remoteChainId() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function remoteToken() external view returns (address);\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n function bridge() external view returns (address);\n\n /**\n * @notice Mints some token ID for a user, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * @param _to Address of the user to mint the token for.\n * @param _tokenId Token ID to mint.\n */\n function safeMint(address _to, uint256 _tokenId) external;\n\n /**\n * @notice Burns a token ID from a user.\n *\n * @param _from Address of the user to burn the token from.\n * @param _tokenId Token ID to burn.\n */\n function burn(address _from, uint256 _tokenId) external;\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n /**\n * @dev Returns the total amount of tokens stored by the contract.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n /**\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n * Use along with {totalSupply} to enumerate all tokens.\n */\n function tokenByIndex(uint256 index) external view returns (uint256);\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismMintableERC721 } from \"./OptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC721Factory\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\n */\ncontract OptimismMintableERC721Factory is Semver {\n /**\n * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\n *\n * @param localToken Address of the token on the this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param deployer Address of the initiator of the deployment\n */\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n address public immutable bridge;\n\n /**\n * @notice Chain ID for the remote network.\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 0, 0) {\n require(\n _bridge != address(0),\n \"OptimismMintableERC721Factory: bridge cannot be address(0)\"\n );\n require(\n _remoteChainId != 0,\n \"OptimismMintableERC721Factory: remote chain id cannot be zero\"\n );\n\n bridge = _bridge;\n remoteChainId = _remoteChainId;\n }\n\n /**\n * @notice Creates an instance of the standard ERC721.\n *\n * @param _remoteToken Address of the corresponding token on the other domain.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n function createOptimismMintableERC721(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721Factory: L1 token address cannot be address(0)\"\n );\n\n address localToken = address(\n new OptimismMintableERC721(bridge, remoteChainId, _remoteToken, _name, _symbol)\n );\n\n isOptimismMintableERC721[localToken] = true;\n emit OptimismMintableERC721Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n ERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { IOptimismMintableERC721 } from \"./IOptimismMintableERC721.sol\";\n\n/**\n * @title OptimismMintableERC721\n * @notice This contract is the remote representation for some token that lives on another network,\n * typically an Optimism representation of an Ethereum-based token. Standard reference\n * implementation that can be extended or modified according to your needs.\n */\ncontract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable remoteToken;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable bridge;\n\n /**\n * @notice Base token URI for this token.\n */\n string public baseTokenURI;\n\n /**\n * @param _bridge Address of the bridge on this network.\n * @param _remoteChainId Chain ID where the remote token is deployed.\n * @param _remoteToken Address of the corresponding token on the other network.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n constructor(\n address _bridge,\n uint256 _remoteChainId,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC721(_name, _symbol) {\n require(_bridge != address(0), \"OptimismMintableERC721: bridge cannot be address(0)\");\n require(_remoteChainId != 0, \"OptimismMintableERC721: remote chain id cannot be zero\");\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721: remote token cannot be address(0)\"\n );\n\n remoteChainId = _remoteChainId;\n remoteToken = _remoteToken;\n bridge = _bridge;\n\n // Creates a base URI in the format specified by EIP-681:\n // https://eips.ethereum.org/EIPS/eip-681\n baseTokenURI = string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(_remoteToken), 20),\n \"@\",\n Strings.toString(_remoteChainId),\n \"/tokenURI?uint256=\"\n )\n );\n }\n\n /**\n * @notice Modifier that prevents callers other than the bridge from calling the function.\n */\n modifier onlyBridge() {\n require(msg.sender == bridge, \"OptimismMintableERC721: only bridge can call this function\");\n _;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {\n _safeMint(_to, _tokenId);\n\n emit Mint(_to, _tokenId);\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function burn(address _from, uint256 _tokenId) external virtual onlyBridge {\n _burn(_tokenId);\n\n emit Burn(_from, _tokenId);\n }\n\n /**\n * @notice Checks if a given interface ID is supported by this contract.\n *\n * @param _interfaceId The interface ID to check.\n *\n * @return True if the interface ID is supported, false otherwise.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n override(ERC721Enumerable, IERC165)\n returns (bool)\n {\n bytes4 iface1 = type(IERC165).interfaceId;\n bytes4 iface2 = type(IOptimismMintableERC721).interfaceId;\n return\n _interfaceId == iface1 ||\n _interfaceId == iface2 ||\n super.supportsInterface(_interfaceId);\n }\n\n /**\n * @notice Returns the base token URI.\n *\n * @return Base token URI.\n */\n function _baseURI() internal view virtual override returns (string memory) {\n return baseTokenURI;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721.sol\";\nimport \"./IERC721Enumerable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\n // Mapping from owner to list of owned token IDs\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n // Mapping from token ID to index of the owner tokens list\n mapping(uint256 => uint256) private _ownedTokensIndex;\n\n // Array with all token ids, used for enumeration\n uint256[] private _allTokens;\n\n // Mapping from token id to position in the allTokens array\n mapping(uint256 => uint256) private _allTokensIndex;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721.balanceOf(owner), \"ERC721Enumerable: owner index out of bounds\");\n return _ownedTokens[owner][index];\n }\n\n /**\n * @dev See {IERC721Enumerable-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _allTokens.length;\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenByIndex}.\n */\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721Enumerable.totalSupply(), \"ERC721Enumerable: global index out of bounds\");\n return _allTokens[index];\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, tokenId);\n\n if (from == address(0)) {\n _addTokenToAllTokensEnumeration(tokenId);\n } else if (from != to) {\n _removeTokenFromOwnerEnumeration(from, tokenId);\n }\n if (to == address(0)) {\n _removeTokenFromAllTokensEnumeration(tokenId);\n } else if (to != from) {\n _addTokenToOwnerEnumeration(to, tokenId);\n }\n }\n\n /**\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\n * @param to address representing the new owner of the given token ID\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n */\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n uint256 length = ERC721.balanceOf(to);\n _ownedTokens[to][length] = tokenId;\n _ownedTokensIndex[tokenId] = length;\n }\n\n /**\n * @dev Private function to add a token to this extension's token tracking data structures.\n * @param tokenId uint256 ID of the token to be added to the tokens list\n */\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n _allTokensIndex[tokenId] = _allTokens.length;\n _allTokens.push(tokenId);\n }\n\n /**\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n * @param from address representing the previous owner of the given token ID\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n */\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary\n if (tokenIndex != lastTokenIndex) {\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\n\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n }\n\n // This also deletes the contents at the last position of the array\n delete _ownedTokensIndex[tokenId];\n delete _ownedTokens[from][lastTokenIndex];\n }\n\n /**\n * @dev Private function to remove a token from this extension's token tracking data structures.\n * This has O(1) time complexity, but alters the order of the _allTokens array.\n * @param tokenId uint256 ID of the token to be removed from the tokens list\n */\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = _allTokens.length - 1;\n uint256 tokenIndex = _allTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n uint256 lastTokenId = _allTokens[lastTokenIndex];\n\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n // This also deletes the contents at the last position of the array\n delete _allTokensIndex[tokenId];\n _allTokens.pop();\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: balance query for the zero address\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _owners[tokenId];\n require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not owner nor approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n _safeTransfer(from, to, tokenId, _data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _owners[tokenId] != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, _data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId);\n\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId);\n\n // Clear approvals\n _approve(address(0), tokenId);\n\n _balances[owner] -= 1;\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId);\n\n // Clear approvals from the previous owner\n _approve(address(0), tokenId);\n\n _balances[from] -= 1;\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits a {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/AddressManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:legacy\n * @title AddressManager\n * @notice AddressManager is a legacy contract that was used in the old version of the Optimism\n * system to manage a registry of string names to addresses. We now use a more standard\n * proxy system instead, but this contract is still necessary for backwards compatibility\n * with several older contracts.\n */\ncontract AddressManager is Ownable {\n /**\n * @notice Mapping of the hashes of string names to addresses.\n */\n mapping(bytes32 => address) private addresses;\n\n /**\n * @notice Emitted when an address is modified in the registry.\n *\n * @param name String name being set in the registry.\n * @param newAddress Address set for the given name.\n * @param oldAddress Address that was previously set for the given name.\n */\n event AddressSet(string indexed name, address newAddress, address oldAddress);\n\n /**\n * @notice Changes the address associated with a particular name.\n *\n * @param _name String name to associate an address with.\n * @param _address Address to associate with the name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n bytes32 nameHash = _getNameHash(_name);\n address oldAddress = addresses[nameHash];\n addresses[nameHash] = _address;\n\n emit AddressSet(_name, _address, oldAddress);\n }\n\n /**\n * @notice Retrieves the address associated with a given name.\n *\n * @param _name Name to retrieve an address for.\n *\n * @return Address associated with the given name.\n */\n function getAddress(string memory _name) external view returns (address) {\n return addresses[_getNameHash(_name)];\n }\n\n /**\n * @notice Computes the hash of a name.\n *\n * @param _name Name to compute a hash for.\n *\n * @return Hash of the given name.\n */\n function _getNameHash(string memory _name) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(_name));\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\nimport { Proxy } from \"./Proxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\n\n/**\n * @title IStaticERC1967Proxy\n * @notice IStaticERC1967Proxy is a static version of the ERC1967 proxy interface.\n */\ninterface IStaticERC1967Proxy {\n function implementation() external view returns (address);\n\n function admin() external view returns (address);\n}\n\n/**\n * @title IStaticL1ChugSplashProxy\n * @notice IStaticL1ChugSplashProxy is a static version of the ChugSplash proxy interface.\n */\ninterface IStaticL1ChugSplashProxy {\n function getImplementation() external view returns (address);\n\n function getOwner() external view returns (address);\n}\n\n/**\n * @title ProxyAdmin\n * @notice This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy,\n * based on the OpenZeppelin implementation. It has backwards compatibility logic to work\n * with the various types of proxies that have been deployed by Optimism in the past.\n */\ncontract ProxyAdmin is Owned {\n /**\n * @notice The proxy types that the ProxyAdmin can manage.\n *\n * @custom:value ERC1967 Represents an ERC1967 compliant transparent proxy interface.\n * @custom:value CHUGSPLASH Represents the Chugsplash proxy interface (legacy).\n * @custom:value RESOLVED Represents the ResolvedDelegate proxy (legacy).\n */\n enum ProxyType {\n ERC1967,\n CHUGSPLASH,\n RESOLVED\n }\n\n /**\n * @custom:legacy\n * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\n * @custom:legacy\n * @notice A reverse mapping of addresses to names held in the AddressManager. This must be\n * manually kept up to date with changes in the AddressManager for this contract\n * to be able to work as an admin for the ResolvedDelegateProxy type.\n */\n mapping(address => string) public implementationName;\n\n /**\n * @custom:legacy\n * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @custom:legacy\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading = false;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * @notice Sets the proxy type for a given address. Only required for non-standard (legacy)\n * proxy types.\n *\n * @param _address Address of the proxy.\n * @param _type Type of the proxy.\n */\n function setProxyType(address _address, ProxyType _type) external onlyOwner {\n proxyType[_address] = _type;\n }\n\n /**\n * @notice Sets the implementation name for a given address. Only required for\n * ResolvedDelegateProxy type proxies that have an implementation name.\n *\n * @param _address Address of the ResolvedDelegateProxy.\n * @param _name Name of the implementation for the proxy.\n */\n function setImplementationName(address _address, string memory _name) external onlyOwner {\n implementationName[_address] = _name;\n }\n\n /**\n * @notice Set the address of the AddressManager. This is required to manage legacy\n * ResolvedDelegateProxy type proxy contracts.\n *\n * @param _address Address of the AddressManager.\n */\n function setAddressManager(AddressManager _address) external onlyOwner {\n addressManager = _address;\n }\n\n /**\n * @custom:legacy\n * @notice Set an address in the address manager. Since only the owner of the AddressManager\n * can directly modify addresses and the ProxyAdmin will own the AddressManager, this\n * gives the owner of the ProxyAdmin the ability to modify addresses directly.\n *\n * @param _name Name to set within the AddressManager.\n * @param _address Address to attach to the given name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n addressManager.setAddress(_name, _address);\n }\n\n /**\n * @custom:legacy\n * @notice Set the upgrading status for the Chugsplash proxy type.\n *\n * @param _upgrading Whether or not the system is upgrading.\n */\n function setUpgrading(bool _upgrading) external onlyOwner {\n upgrading = _upgrading;\n }\n\n /**\n * @notice Updates the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to update.\n * @param _newAdmin Address of the new proxy admin.\n */\n function changeProxyAdmin(address payable _proxy, address _newAdmin) external onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).changeAdmin(_newAdmin);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setOwner(_newAdmin);\n } else if (ptype == ProxyType.RESOLVED) {\n addressManager.transferOwnership(_newAdmin);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract and delegatecalls the new implementation\n * with some given data. Useful for atomic upgrade-and-initialize calls.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n * @param _data Data to trigger the new implementation with.\n */\n function upgradeAndCall(\n address payable _proxy,\n address _implementation,\n bytes memory _data\n ) external payable onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeToAndCall{ value: msg.value }(_implementation, _data);\n } else {\n // reverts if proxy type is unknown\n upgrade(_proxy, _implementation);\n (bool success, ) = _proxy.call{ value: msg.value }(_data);\n require(success, \"ProxyAdmin: call to proxy after upgrade failed\");\n }\n }\n\n /**\n * @custom:legacy\n * @notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\n *\n * @return Whether or not there is an upgrade going on. May not actually tell you whether an\n * upgrade is going on, since we don't currently plan to use this variable for anything\n * other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\n */\n function isUpgrading() external view returns (bool) {\n return upgrading;\n }\n\n /**\n * @notice Returns the implementation of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the implementation of.\n *\n * @return Address of the implementation of the proxy.\n */\n function getProxyImplementation(address _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).implementation();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getImplementation();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.getAddress(implementationName[_proxy]);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Returns the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the admin of.\n *\n * @return Address of the admin of the proxy.\n */\n function getProxyAdmin(address payable _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).admin();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getOwner();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.owner();\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n */\n function upgrade(address payable _proxy, address _implementation) public onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeTo(_implementation);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setStorage(\n // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,\n bytes32(uint256(uint160(_implementation)))\n );\n } else if (ptype == ProxyType.RESOLVED) {\n string memory name = implementationName[_proxy];\n addressManager.setAddress(name, _implementation);\n } else {\n // It should not be possible to retrieve a ProxyType value which is not matched by\n // one of the previous conditions.\n assert(false);\n }\n }\n}\n" + }, + "@rari-capital/solmate/src/auth/Owned.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol)\nabstract contract Owned {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event OwnerUpdated(address indexed user, address indexed newOwner);\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP STORAGE\n //////////////////////////////////////////////////////////////*/\n\n address public owner;\n\n modifier onlyOwner() virtual {\n require(msg.sender == owner, \"UNAUTHORIZED\");\n\n _;\n }\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(address _owner) {\n owner = _owner;\n\n emit OwnerUpdated(address(0), _owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function setOwner(address newOwner) public virtual onlyOwner {\n owner = newOwner;\n\n emit OwnerUpdated(msg.sender, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Proxy\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\n * if the caller is address(0), meaning that the call originated from an off-chain\n * simulation.\n */\ncontract Proxy {\n /**\n * @notice The storage slot that holds the address of the implementation.\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice The storage slot that holds the address of the owner.\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice An event that is emitted each time the implementation is changed. This event is part\n * of the EIP-1967 specification.\n *\n * @param implementation The address of the implementation contract\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\n * EIP-1967 specification.\n *\n * @param previousAdmin The previous owner of the contract\n * @param newAdmin The new owner of the contract\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\n * eth_call to interact with this proxy without needing to use low-level storage\n * inspection. We assume that nobody is able to trigger calls from address(0) during\n * normal EVM execution.\n */\n modifier proxyCallIfNotAdmin() {\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\n * EIP-1967 admin storage slot so that accidental storage collision with the\n * implementation is not possible.\n *\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\n * transparent proxy interface.\n */\n constructor(address _admin) {\n _changeAdmin(_admin);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Set the implementation contract address. The code at the given address will execute\n * when this contract is called.\n *\n * @param _implementation Address of the implementation contract.\n */\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\n _setImplementation(_implementation);\n }\n\n /**\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\n * atomic execution of initialization-based upgrades.\n *\n * @param _implementation Address of the implementation contract.\n * @param _data Calldata to delegatecall the new implementation with.\n */\n function upgradeToAndCall(address _implementation, bytes calldata _data)\n external\n payable\n proxyCallIfNotAdmin\n returns (bytes memory)\n {\n _setImplementation(_implementation);\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\n require(success, \"Proxy: delegatecall to new implementation contract failed\");\n return returndata;\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _admin New owner of the proxy contract.\n */\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\n _changeAdmin(_admin);\n }\n\n /**\n * @notice Gets the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function admin() external proxyCallIfNotAdmin returns (address) {\n return _getAdmin();\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function implementation() external proxyCallIfNotAdmin returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n emit Upgraded(_implementation);\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _admin New owner of the proxy contract.\n */\n function _changeAdmin(address _admin) internal {\n address previous = _getAdmin();\n assembly {\n sstore(OWNER_KEY, _admin)\n }\n emit AdminChanged(previous, _admin);\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal {\n address impl = _getImplementation();\n require(impl != address(0), \"Proxy: implementation not initialized\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address impl;\n assembly {\n impl := sload(IMPLEMENTATION_KEY)\n }\n return impl;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getAdmin() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/L1ChugSplashProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title IL1ChugSplashDeployer\n */\ninterface IL1ChugSplashDeployer {\n function isUpgrading() external view returns (bool);\n}\n\n/**\n * @custom:legacy\n * @title L1ChugSplashProxy\n * @notice Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added\n * functions `setCode` and `setStorage` for changing the code or storage of the contract.\n *\n * Note for future developers: do NOT make anything in this contract 'public' unless you\n * know what you're doing. Anything public can potentially have a function signature that\n * conflicts with a signature attached to the implementation contract. Public functions\n * SHOULD always have the `proxyCallIfNotOwner` modifier unless there's some *really* good\n * reason not to have that modifier. And there almost certainly is not a good reason to not\n * have that modifier. Beware!\n */\ncontract L1ChugSplashProxy {\n /**\n * @notice \"Magic\" prefix. When prepended to some arbitrary bytecode and used to create a\n * contract, the appended bytecode will be deployed as given.\n */\n bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice Blocks a function from being called when the parent signals that the system should\n * be paused via an isUpgrading function.\n */\n modifier onlyWhenNotPaused() {\n address owner = _getOwner();\n\n // We do a low-level call because there's no guarantee that the owner actually *is* an\n // L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and\n // it turns out that it isn't the right type of contract.\n (bool success, bytes memory returndata) = owner.staticcall(\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector)\n );\n\n // If the call was unsuccessful then we assume that there's no \"isUpgrading\" method and we\n // can just continue as normal. We also expect that the return value is exactly 32 bytes\n // long. If this isn't the case then we can safely ignore the result.\n if (success && returndata.length == 32) {\n // Although the expected value is a *boolean*, it's safer to decode as a uint256 in the\n // case that the isUpgrading function returned something other than 0 or 1. But we only\n // really care about the case where this value is 0 (= false).\n uint256 ret = abi.decode(returndata, (uint256));\n require(ret == 0, \"L1ChugSplashProxy: system is currently being upgraded\");\n }\n\n _;\n }\n\n /**\n * @notice Makes a proxy call instead of triggering the given function when the caller is\n * either the owner or the zero address. Caller can only ever be the zero address if\n * this function is being called off-chain via eth_call, which is totally fine and can\n * be convenient for client-side tooling. Avoids situations where the proxy and\n * implementation share a sighash and the proxy function ends up being called instead\n * of the implementation one.\n *\n * Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If\n * there's a way for someone to send a transaction with msg.sender == address(0) in any\n * real context then we have much bigger problems. Primary reason to include this\n * additional allowed sender is because the owner address can be changed dynamically\n * and we do not want clients to have to keep track of the current owner in order to\n * make an eth_call that doesn't trigger the proxied contract.\n */\n // slither-disable-next-line incorrect-modifier\n modifier proxyCallIfNotOwner() {\n if (msg.sender == _getOwner() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @param _owner Address of the initial contract owner.\n */\n constructor(address _owner) {\n _setOwner(_owner);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Sets the code that should be running behind this proxy.\n *\n * Note: This scheme is a bit different from the standard proxy scheme where one would\n * typically deploy the code separately and then set the implementation address. We're\n * doing it this way because it gives us a lot more freedom on the client side. Can\n * only be triggered by the contract owner.\n *\n * @param _code New contract code to run inside this contract.\n */\n function setCode(bytes memory _code) external proxyCallIfNotOwner {\n // Get the code hash of the current implementation.\n address implementation = _getImplementation();\n\n // If the code hash matches the new implementation then we return early.\n if (keccak256(_code) == _getAccountCodeHash(implementation)) {\n return;\n }\n\n // Create the deploycode by appending the magic prefix.\n bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code);\n\n // Deploy the code and set the new implementation address.\n address newImplementation;\n assembly {\n newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode))\n }\n\n // Check that the code was actually deployed correctly. I'm not sure if you can ever\n // actually fail this check. Should only happen if the contract creation from above runs\n // out of gas but this parent execution thread does NOT run out of gas. Seems like we\n // should be doing this check anyway though.\n require(\n _getAccountCodeHash(newImplementation) == keccak256(_code),\n \"L1ChugSplashProxy: code was not correctly deployed\"\n );\n\n _setImplementation(newImplementation);\n }\n\n /**\n * @notice Modifies some storage slot within the proxy contract. Gives us a lot of power to\n * perform upgrades in a more transparent way. Only callable by the owner.\n *\n * @param _key Storage key to modify.\n * @param _value New value for the storage key.\n */\n function setStorage(bytes32 _key, bytes32 _value) external proxyCallIfNotOwner {\n assembly {\n sstore(_key, _value)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _owner New owner of the proxy contract.\n */\n function setOwner(address _owner) external proxyCallIfNotOwner {\n _setOwner(_owner);\n }\n\n /**\n * @notice Queries the owner of the proxy contract. Can only be called by the owner OR by\n * making an eth_call and setting the \"from\" address to address(0).\n *\n * @return Owner address.\n */\n function getOwner() external proxyCallIfNotOwner returns (address) {\n return _getOwner();\n }\n\n /**\n * @notice Queries the implementation address. Can only be called by the owner OR by making an\n * eth_call and setting the \"from\" address to address(0).\n *\n * @return Implementation address.\n */\n function getImplementation() external proxyCallIfNotOwner returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _owner New owner of the proxy contract.\n */\n function _setOwner(address _owner) internal {\n assembly {\n sstore(OWNER_KEY, _owner)\n }\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal onlyWhenNotPaused {\n address implementation = _getImplementation();\n\n require(implementation != address(0), \"L1ChugSplashProxy: implementation is not set yet\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address implementation;\n assembly {\n implementation := sload(IMPLEMENTATION_KEY)\n }\n return implementation;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getOwner() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n\n /**\n * @notice Gets the code hash for a given account.\n *\n * @param _account Address of the account to get a code hash for.\n *\n * @return Code hash for the account.\n */\n function _getAccountCodeHash(address _account) internal view returns (bytes32) {\n bytes32 codeHash;\n assembly {\n codeHash := extcodehash(_account)\n }\n return codeHash;\n }\n}\n" + }, + "contracts/testing/helpers/ExternalContractCompiler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ProxyAdmin } from \"@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol\";\nimport { Proxy } from \"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\";\n\n/**\n * Just exists so we can compile external contracts.\n */\ncontract ExternalContractCompiler {\n\n}\n" + }, + "contracts/testing/helpers/TestERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\n\ncontract TestERC721 is ERC721 {\n constructor() ERC721(\"TEST\", \"TST\") {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n\n function tokenURI(uint256) public pure virtual override returns (string memory) {}\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 indexed id);\n\n event Approval(address indexed owner, address indexed spender, uint256 indexed id);\n\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE/LOGIC\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n function tokenURI(uint256 id) public view virtual returns (string memory);\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) internal _ownerOf;\n\n mapping(address => uint256) internal _balanceOf;\n\n function ownerOf(uint256 id) public view virtual returns (address owner) {\n require((owner = _ownerOf[id]) != address(0), \"NOT_MINTED\");\n }\n\n function balanceOf(address owner) public view virtual returns (uint256) {\n require(owner != address(0), \"ZERO_ADDRESS\");\n\n return _balanceOf[owner];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) public getApproved;\n\n mapping(address => mapping(address => bool)) public isApprovedForAll;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(string memory _name, string memory _symbol) {\n name = _name;\n symbol = _symbol;\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 id) public virtual {\n address owner = _ownerOf[id];\n\n require(msg.sender == owner || isApprovedForAll[owner][msg.sender], \"NOT_AUTHORIZED\");\n\n getApproved[id] = spender;\n\n emit Approval(owner, spender, id);\n }\n\n function setApprovalForAll(address operator, bool approved) public virtual {\n isApprovedForAll[msg.sender][operator] = approved;\n\n emit ApprovalForAll(msg.sender, operator, approved);\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n require(from == _ownerOf[id], \"WRONG_FROM\");\n\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(\n msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],\n \"NOT_AUTHORIZED\"\n );\n\n // Underflow of the sender's balance is impossible because we check for\n // ownership above and the recipient's balance can't realistically overflow.\n unchecked {\n _balanceOf[from]--;\n\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n delete getApproved[id];\n\n emit Transfer(from, to, id);\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n bytes calldata data\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return\n interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165\n interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721\n interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 id) internal virtual {\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(_ownerOf[id] == address(0), \"ALREADY_MINTED\");\n\n // Counter overflow is incredibly unrealistic.\n unchecked {\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n emit Transfer(address(0), to, id);\n }\n\n function _burn(uint256 id) internal virtual {\n address owner = _ownerOf[id];\n\n require(owner != address(0), \"NOT_MINTED\");\n\n // Ownership check above ensures no underflow.\n unchecked {\n _balanceOf[owner]--;\n }\n\n delete _ownerOf[id];\n\n delete getApproved[id];\n\n emit Transfer(owner, address(0), id);\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL SAFE MINT LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _safeMint(address to, uint256 id) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function _safeMint(\n address to,\n uint256 id,\n bytes memory data\n ) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n}\n\n/// @notice A generic interface for a contract which properly accepts ERC721 tokens.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721TokenReceiver {\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n ) external virtual returns (bytes4) {\n return ERC721TokenReceiver.onERC721Received.selector;\n }\n}\n" + }, + "contracts/testing/helpers/TestERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n constructor() ERC20(\"TEST\", \"TST\", 18) {}\n\n function mint(address to, uint256 value) public {\n _mint(to, value);\n }\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "contracts/L1/TeleportrWithdrawer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AssetReceiver } from \"../universal/AssetReceiver.sol\";\n\n/**\n * @notice Stub interface for Teleportr.\n */\ninterface Teleportr {\n function withdrawBalance() external;\n}\n\n/**\n * @title TeleportrWithdrawer\n * @notice The TeleportrWithdrawer is a simple contract capable of withdrawing funds from the\n * TeleportrContract and sending them to some recipient address.\n */\ncontract TeleportrWithdrawer is AssetReceiver {\n /**\n * @notice Address of the Teleportr contract.\n */\n address public teleportr;\n\n /**\n * @notice Address that will receive Teleportr withdrawals.\n */\n address public recipient;\n\n /**\n * @notice Data to be sent to the recipient address.\n */\n bytes public data;\n\n /**\n * @param _owner Initial owner of the contract.\n */\n constructor(address _owner) AssetReceiver(_owner) {}\n\n /**\n * @notice Allows the owner to update the recipient address.\n *\n * @param _recipient New recipient address.\n */\n function setRecipient(address _recipient) external onlyOwner {\n recipient = _recipient;\n }\n\n /**\n * @notice Allows the owner to update the Teleportr contract address.\n *\n * @param _teleportr New Teleportr contract address.\n */\n function setTeleportr(address _teleportr) external onlyOwner {\n teleportr = _teleportr;\n }\n\n /**\n * @notice Allows the owner to update the data to be sent to the recipient address.\n *\n * @param _data New data to be sent to the recipient address.\n */\n function setData(bytes memory _data) external onlyOwner {\n data = _data;\n }\n\n /**\n * @notice Withdraws the full balance of the Teleportr contract to the recipient address.\n * Anyone is allowed to trigger this function since the recipient address cannot be\n * controlled by the msg.sender.\n */\n function withdrawFromTeleportr() external {\n Teleportr(teleportr).withdrawBalance();\n (bool success, ) = recipient.call{ value: address(this).balance }(data);\n require(success, \"TeleportrWithdrawer: send failed\");\n }\n}\n" + }, + "contracts/universal/AssetReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\nimport { Transactor } from \"./Transactor.sol\";\n\n/**\n * @title AssetReceiver\n * @notice AssetReceiver is a minimal contract for receiving funds assets in the form of either\n * ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.\n */\ncontract AssetReceiver is Transactor {\n /**\n * @notice Emitted when ETH is received by this address.\n *\n * @param from Address that sent ETH to this contract.\n * @param amount Amount of ETH received.\n */\n event ReceivedETH(address indexed from, uint256 amount);\n\n /**\n * @notice Emitted when ETH is withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param amount ETH amount withdrawn.\n */\n event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param amount ERC20 amount withdrawn.\n */\n event WithdrewERC20(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 amount\n );\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param id Token ID being withdrawn.\n */\n event WithdrewERC721(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 id\n );\n\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Transactor(_owner) {}\n\n /**\n * @notice Make sure we can receive ETH.\n */\n receive() external payable {\n emit ReceivedETH(msg.sender, msg.value);\n }\n\n /**\n * @notice Withdraws full ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n */\n function withdrawETH(address payable _to) external onlyOwner {\n withdrawETH(_to, address(this).balance);\n }\n\n /**\n * @notice Withdraws partial ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n * @param _amount Amount of ETH to withdraw.\n */\n function withdrawETH(address payable _to, uint256 _amount) public onlyOwner {\n // slither-disable-next-line reentrancy-unlimited-gas\n (bool success, ) = _to.call{ value: _amount }(\"\");\n emit WithdrewETH(msg.sender, _to, _amount);\n }\n\n /**\n * @notice Withdraws full ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n */\n function withdrawERC20(ERC20 _asset, address _to) external onlyOwner {\n withdrawERC20(_asset, _to, _asset.balanceOf(address(this)));\n }\n\n /**\n * @notice Withdraws partial ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n * @param _amount Amount of ERC20 to withdraw.\n */\n function withdrawERC20(\n ERC20 _asset,\n address _to,\n uint256 _amount\n ) public onlyOwner {\n // slither-disable-next-line unchecked-transfer\n _asset.transfer(_to, _amount);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC20(msg.sender, _to, address(_asset), _amount);\n }\n\n /**\n * @notice Withdraws ERC721 token to the recipient.\n *\n * @param _asset ERC721 token to withdraw.\n * @param _to Address to receive the ERC721 token.\n * @param _id Token ID of the ERC721 token to withdraw.\n */\n function withdrawERC721(\n ERC721 _asset,\n address _to,\n uint256 _id\n ) external onlyOwner {\n _asset.transferFrom(address(this), _to, _id);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC721(msg.sender, _to, address(_asset), _id);\n }\n}\n" + }, + "contracts/universal/Transactor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\n\n/**\n * @title Transactor\n * @notice Transactor is a minimal contract that can send transactions.\n */\ncontract Transactor is Owned {\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * Sends a CALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n * @param _value ETH value to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function CALL(\n address _target,\n bytes memory _data,\n uint256 _value\n ) external payable onlyOwner returns (bool, bytes memory) {\n return _target.call{ value: _value }(_data);\n }\n\n /**\n * Sends a DELEGATECALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function DELEGATECALL(address _target, bytes memory _data)\n external\n payable\n onlyOwner\n returns (bool, bytes memory)\n {\n // slither-disable-next-line controlled-delegatecall\n return _target.delegatecall(_data);\n }\n}\n" + }, + "contracts/L2/TeleportrDisburser.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title TeleportrDisburser\n */\ncontract TeleportrDisburser is Ownable {\n /**\n * @notice A struct holding the address and amount to disbursement.\n */\n struct Disbursement {\n uint256 amount;\n address addr;\n }\n\n /**\n * @notice Total number of disbursements processed.\n */\n uint256 public totalDisbursements;\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a disbursement is successfuly sent.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The recipient of the disbursement.\n * @param amount The amount sent to the recipient.\n */\n event DisbursementSuccess(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @notice Emitted any time a disbursement fails to send.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The intended recipient of the disbursement.\n * @param amount The amount intended to be sent to the recipient.\n */\n event DisbursementFailed(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @custom:semver 0.0.1\n */\n constructor() {\n totalDisbursements = 0;\n }\n\n /**\n * @notice Accepts a list of Disbursements and forwards the amount paid to the contract to each\n * recipient. Reverts if there are zero disbursements, the total amount to forward\n * differs from the amount sent in the transaction, or the _nextDepositId is\n * unexpected. Failed disbursements will not cause the method to revert, but will\n * instead be held by the contract and available for the owner to withdraw.\n *\n * @param _nextDepositId The depositId of the first Dispursement.\n * @param _disbursements A list of Disbursements to process.\n */\n function disburse(uint256 _nextDepositId, Disbursement[] calldata _disbursements)\n external\n payable\n onlyOwner\n {\n // Ensure there are disbursements to process.\n uint256 _numDisbursements = _disbursements.length;\n require(_numDisbursements > 0, \"No disbursements\");\n\n // Ensure the _nextDepositId matches our expected value.\n uint256 _depositId = totalDisbursements;\n require(_depositId == _nextDepositId, \"Unexpected next deposit id\");\n unchecked {\n totalDisbursements += _numDisbursements;\n }\n\n // Ensure the amount sent in the transaction is equal to the sum of the\n // disbursements.\n uint256 _totalDisbursed = 0;\n for (uint256 i = 0; i < _numDisbursements; i++) {\n _totalDisbursed += _disbursements[i].amount;\n }\n require(_totalDisbursed == msg.value, \"Disbursement total != amount sent\");\n\n // Process disbursements.\n for (uint256 i = 0; i < _numDisbursements; i++) {\n uint256 _amount = _disbursements[i].amount;\n address _addr = _disbursements[i].addr;\n\n // Deliver the dispursement amount to the receiver. If the\n // disbursement fails, the amount will be kept by the contract\n // rather than reverting to prevent blocking progress on other\n // disbursements.\n\n // slither-disable-next-line calls-loop,reentrancy-events\n (bool success, ) = _addr.call{ value: _amount, gas: 2300 }(\"\");\n if (success) emit DisbursementSuccess(_depositId, _addr, _amount);\n else emit DisbursementFailed(_depositId, _addr, _amount);\n\n unchecked {\n _depositId += 1;\n }\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 balance = address(this).balance;\n emit BalanceWithdrawn(_owner, balance);\n payable(_owner).transfer(balance);\n }\n}\n" + }, + "contracts/L1/TeleportrDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:attribution https://github.com/0xclem/teleportr\n * @title TeleportrDeposit\n * @notice A contract meant to manage deposits into Optimism's Teleportr custodial bridge. Deposits\n * are rate limited to avoid a situation where too much ETH is flowing through this bridge\n * and cannot be properly disbursed on L2. Inspired by 0xclem's original Teleportr system\n * (https://github.com/0xclem/teleportr).\n */\ncontract TeleportrDeposit is Ownable {\n /**\n * @notice Minimum deposit amount (in wei).\n */\n uint256 public minDepositAmount;\n\n /**\n * @notice Maximum deposit amount (in wei).\n */\n uint256 public maxDepositAmount;\n\n /**\n * @notice Maximum balance this contract will hold before it starts rejecting deposits.\n */\n uint256 public maxBalance;\n\n /**\n * @notice Total number of deposits received.\n */\n uint256 public totalDeposits;\n\n /**\n * @notice Emitted any time the minimum deposit amount is set.\n *\n * @param previousAmount The previous minimum deposit amount.\n * @param newAmount The new minimum deposit amount.\n */\n event MinDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the maximum deposit amount is set.\n *\n * @param previousAmount The previous maximum deposit amount.\n * @param newAmount The new maximum deposit amount.\n */\n event MaxDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the contract maximum balance is set.\n *\n * @param previousBalance The previous maximum contract balance.\n * @param newBalance The new maximum contract balance.\n */\n event MaxBalanceSet(uint256 previousBalance, uint256 newBalance);\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a successful deposit is received.\n *\n * @param depositId A unique sequencer number identifying the deposit.\n * @param emitter The sending address of the payer.\n * @param amount The amount deposited by the payer.\n */\n event EtherReceived(uint256 indexed depositId, address indexed emitter, uint256 indexed amount);\n\n /**\n * @custom:semver 0.0.1\n *\n * @param _minDepositAmount The initial minimum deposit amount.\n * @param _maxDepositAmount The initial maximum deposit amount.\n * @param _maxBalance The initial maximum contract balance.\n */\n constructor(\n uint256 _minDepositAmount,\n uint256 _maxDepositAmount,\n uint256 _maxBalance\n ) {\n minDepositAmount = _minDepositAmount;\n maxDepositAmount = _maxDepositAmount;\n maxBalance = _maxBalance;\n totalDeposits = 0;\n emit MinDepositAmountSet(0, _minDepositAmount);\n emit MaxDepositAmountSet(0, _maxDepositAmount);\n emit MaxBalanceSet(0, _maxBalance);\n }\n\n /**\n * @notice Accepts deposits that will be disbursed to the sender's address on L2.\n */\n receive() external payable {\n require(msg.value >= minDepositAmount, \"Deposit amount is too small\");\n require(msg.value <= maxDepositAmount, \"Deposit amount is too big\");\n require(address(this).balance <= maxBalance, \"Contract max balance exceeded\");\n\n emit EtherReceived(totalDeposits, msg.sender, msg.value);\n unchecked {\n totalDeposits += 1;\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 _balance = address(this).balance;\n emit BalanceWithdrawn(_owner, _balance);\n payable(_owner).transfer(_balance);\n }\n\n /**\n * @notice Sets the minimum amount that can be deposited in a receive.\n *\n * @param _minDepositAmount The new minimum deposit amount.\n */\n function setMinAmount(uint256 _minDepositAmount) external onlyOwner {\n emit MinDepositAmountSet(minDepositAmount, _minDepositAmount);\n minDepositAmount = _minDepositAmount;\n }\n\n /**\n * @notice Sets the maximum amount that can be deposited in a receive.\n *\n * @param _maxDepositAmount The new maximum deposit amount.\n */\n function setMaxAmount(uint256 _maxDepositAmount) external onlyOwner {\n emit MaxDepositAmountSet(maxDepositAmount, _maxDepositAmount);\n maxDepositAmount = _maxDepositAmount;\n }\n\n /**\n * @notice Sets the maximum balance the contract can hold after a receive.\n *\n * @param _maxBalance The new maximum contract balance.\n */\n function setMaxBalance(uint256 _maxBalance) external onlyOwner {\n emit MaxBalanceSet(maxBalance, _maxBalance);\n maxBalance = _maxBalance;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-kovan/L2ERC721Bridge.json b/packages/contracts-periphery/deployments/optimism-kovan/L2ERC721Bridge.json deleted file mode 100644 index ddd1b707e5b35..0000000000000 --- a/packages/contracts-periphery/deployments/optimism-kovan/L2ERC721Bridge.json +++ /dev/null @@ -1,681 +0,0 @@ -{ - "address": "0x5D263ac19006A65788e788Fb974D7bF5eDC330E7", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_messenger", - "type": "address" - }, - { - "internalType": "address", - "name": "_otherBridge", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC721BridgeFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC721BridgeFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC721BridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "MAJOR_VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MINOR_VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PATCH_VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "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" - } - ], - "name": "bridgeERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "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" - } - ], - "name": "bridgeERC721To", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "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" - } - ], - "name": "finalizeBridgeERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_messenger", - "type": "address" - }, - { - "internalType": "address", - "name": "_otherBridge", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "messenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "otherBridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xa8e36aa5d8fac073d2d13575592d1d773a250545022825473f3dbf76db204190", - "receipt": { - "to": null, - "from": "0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5", - "contractAddress": "0x5D263ac19006A65788e788Fb974D7bF5eDC330E7", - "transactionIndex": 0, - "gasUsed": "1514029", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000001000000001000000000000000800000000000020000000000000000000800000000000000000000000000000000400000000000000080000000000000000000000000000080000000020000000000000000001000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7044a75f4591050a555fa91b50bab2fb37605b7a22269c1509481ec99f4e1ae2", - "transactionHash": "0xa8e36aa5d8fac073d2d13575592d1d773a250545022825473f3dbf76db204190", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 4498529, - "transactionHash": "0xa8e36aa5d8fac073d2d13575592d1d773a250545022825473f3dbf76db204190", - "address": "0x5D263ac19006A65788e788Fb974D7bF5eDC330E7", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000c37f6a6c4ab335e20d10f034b90386e2fb70bbf5" - ], - "data": "0x", - "logIndex": 0, - "blockHash": "0x7044a75f4591050a555fa91b50bab2fb37605b7a22269c1509481ec99f4e1ae2" - }, - { - "transactionIndex": 0, - "blockNumber": 4498529, - "transactionHash": "0xa8e36aa5d8fac073d2d13575592d1d773a250545022825473f3dbf76db204190", - "address": "0x5D263ac19006A65788e788Fb974D7bF5eDC330E7", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 1, - "blockHash": "0x7044a75f4591050a555fa91b50bab2fb37605b7a22269c1509481ec99f4e1ae2" - } - ], - "blockNumber": 4498529, - "cumulativeGasUsed": "1514029", - "status": 1, - "byzantium": true - }, - "args": [ - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000" - ], - "numDeployments": 2, - "solcInputHash": "c6fd6c61d1988656e270189e3651a1e1", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeFailed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAJOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PATCH_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\"}],\"name\":\"bridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}],\"name\":\"bridgeERC721To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}],\"name\":\"finalizeBridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"ERC721BridgeFailed(address,address,address,address,uint256,bytes)\":{\"params\":{\"extraData\":\"Extra data for use on the client-side.\",\"from\":\"Address that initiated bridging action.\",\"localToken\":\"Address of the token on this domain.\",\"remoteToken\":\"Address of the token on the remote domain.\",\"to\":\"Address to receive the token.\",\"tokenId\":\"ID of the specific token deposited.\"}},\"ERC721BridgeFinalized(address,address,address,address,uint256,bytes)\":{\"params\":{\"extraData\":\"Extra data for use on the client-side.\",\"from\":\"Address that initiated bridging action.\",\"localToken\":\"Address of the token on this domain.\",\"remoteToken\":\"Address of the token on the remote domain.\",\"to\":\"Address to receive the token.\",\"tokenId\":\"ID of the specific token deposited.\"}},\"ERC721BridgeInitiated(address,address,address,address,uint256,bytes)\":{\"params\":{\"extraData\":\"Extra data for use on the client-side.\",\"from\":\"Address that initiated bridging action.\",\"localToken\":\"Address of the token on this domain.\",\"remoteToken\":\"Address of the token on the remote domain.\",\"to\":\"Address to receive the token.\",\"tokenId\":\"ID of the specific token deposited.\"}}},\"kind\":\"dev\",\"methods\":{\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to L1. Data supplied here will not be used to execute any code on L1 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 L1. Data supplied here will not be used to execute any code on L1 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.\",\"_otherBridge\":\"Address of the ERC721 bridge on the other network.\"}},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to L1. Data supplied here will not be used to execute any code on L1 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,address)\":{\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\",\"_otherBridge\":\"Address of the ERC721 bridge on the other network.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"L2ERC721Bridge\",\"version\":1},\"userdoc\":{\"events\":{\"ERC721BridgeFailed(address,address,address,address,uint256,bytes)\":{\"notice\":\"Emitted when an ERC721 bridge from the other network fails.\"},\"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.\"}},\"kind\":\"user\",\"methods\":{\"MAJOR_VERSION()\":{\"notice\":\"Contract version number (major).\"},\"MINOR_VERSION()\":{\"notice\":\"Contract version number (minor).\"},\"PATCH_VERSION()\":{\"notice\":\"Contract version number (patch).\"},\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to the caller's account on L1.\"},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to some recipient's account on L1.\"},\"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.\"},\"otherBridge()\":{\"notice\":\"Address of the bridge on the other network.\"}},\"notice\":\"The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to make it possible to transfer ERC721 tokens between Optimism and Ethereum. This contract acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge. This contract also acts as a burner for tokens being withdrawn.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/messaging/L2ERC721Bridge.sol\":\"L2ERC721Bridge\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.9.0;\\n\\n/* Interface Imports */\\nimport { ICrossDomainMessenger } from \\\"./ICrossDomainMessenger.sol\\\";\\n\\n/**\\n * @title CrossDomainEnabled\\n * @dev Helper contract for contracts performing cross-domain communications\\n *\\n * Compiler used: defined by inheriting contract\\n */\\ncontract CrossDomainEnabled {\\n /*************\\n * Variables *\\n *************/\\n\\n // Messenger contract used to send and recieve messages from the other domain.\\n address public messenger;\\n\\n /***************\\n * Constructor *\\n ***************/\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on the current layer.\\n */\\n constructor(address _messenger) {\\n messenger = _messenger;\\n }\\n\\n /**********************\\n * Function Modifiers *\\n **********************/\\n\\n /**\\n * Enforces that the modified function is only callable by a specific cross-domain account.\\n * @param _sourceDomainAccount The only account on the originating domain which is\\n * authenticated to call this function.\\n */\\n modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) {\\n require(\\n msg.sender == address(getCrossDomainMessenger()),\\n \\\"OVM_XCHAIN: messenger contract unauthenticated\\\"\\n );\\n\\n require(\\n getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount,\\n \\\"OVM_XCHAIN: wrong sender of cross-domain message\\\"\\n );\\n\\n _;\\n }\\n\\n /**********************\\n * Internal Functions *\\n **********************/\\n\\n /**\\n * Gets the messenger, usually from storage. This function is exposed in case a child contract\\n * needs to override.\\n * @return The address of the cross-domain messenger contract which should be used.\\n */\\n function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {\\n return ICrossDomainMessenger(messenger);\\n }\\n\\n /**q\\n * Sends a message to an account on another domain\\n * @param _crossDomainTarget The intended recipient on the destination domain\\n * @param _message The data to send to the target (usually calldata to a function with\\n * `onlyFromCrossDomainAccount()`)\\n * @param _gasLimit The gasLimit for the receipt of the message on the target domain.\\n */\\n function sendCrossDomainMessage(\\n address _crossDomainTarget,\\n uint32 _gasLimit,\\n bytes memory _message\\n ) internal {\\n // slither-disable-next-line reentrancy-events, reentrancy-benign\\n getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);\\n }\\n}\\n\",\"keccak256\":\"0x9c3cc8b7047c68a403529b15769a21c2e2668ea71db7bef51f123288009811ea\",\"license\":\"MIT\"},\"@eth-optimism/contracts/contracts/libraries/bridge/ICrossDomainMessenger.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.9.0;\\n\\n/**\\n * @title ICrossDomainMessenger\\n */\\ninterface ICrossDomainMessenger {\\n /**********\\n * Events *\\n **********/\\n\\n event SentMessage(\\n address indexed target,\\n address sender,\\n bytes message,\\n uint256 messageNonce,\\n uint256 gasLimit\\n );\\n event RelayedMessage(bytes32 indexed msgHash);\\n event FailedRelayedMessage(bytes32 indexed msgHash);\\n\\n /*************\\n * Variables *\\n *************/\\n\\n function xDomainMessageSender() external view returns (address);\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * Sends a cross domain message to the target messenger.\\n * @param _target Target contract address.\\n * @param _message Message to send to the target.\\n * @param _gasLimit Gas limit for the provided message.\\n */\\n function sendMessage(\\n address _target,\\n bytes calldata _message,\\n uint32 _gasLimit\\n ) external;\\n}\\n\",\"keccak256\":\"0x8f29ae23021345a20ccac7b5edb3fc38268aef943b65adc8a32e74b80bf1833a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x652fee292f698d8dba81bf287cb71f1682f6483b67ebe601a5f7387dcfc30b34\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = _setInitializedVersion(1);\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\\n * initialization step. This is essential to configure modules that are added through upgrades and that require\\n * initialization.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n */\\n modifier reinitializer(uint8 version) {\\n bool isTopLevelCall = _setInitializedVersion(version);\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(version);\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n */\\n function _disableInitializers() internal virtual {\\n _setInitializedVersion(type(uint8).max);\\n }\\n\\n function _setInitializedVersion(uint8 version) private returns (bool) {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\\n // of initializers, because in other contexts the contract may have been reentered.\\n if (_initializing) {\\n require(\\n version == 1 && !AddressUpgradeable.isContract(address(this)),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n return false;\\n } else {\\n require(_initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n return true;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7454006cccb737612b00104d2f606d728e2818b778e7e55542f063c614ce46ba\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55cf2bd9fc76704ddcdc19834cd288b7de00fc0f298a40ea16a954ae8991db2d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/L1/messaging/L1ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport {\\n CrossDomainEnabled\\n} from \\\"@eth-optimism/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport { IERC721 } from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { L2ERC721Bridge } from \\\"../../L2/messaging/L2ERC721Bridge.sol\\\";\\nimport { Semver } from \\\"../../universal/Semver.sol\\\";\\n\\n/**\\n * @title L1ERC721Bridge\\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens between Optimism and Ethereum. This contract\\n * acts as an escrow for ERC721 tokens deposted into L2.\\n */\\ncontract L1ERC721Bridge is Semver, CrossDomainEnabled, OwnableUpgradeable {\\n /**\\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeInitiated(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFinalized(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Address of the bridge on the other network.\\n */\\n address public otherBridge;\\n\\n // Maps L1 token to L2 token to token ID to a boolean indicating if the token is deposited\\n /**\\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\\n * by ID was deposited for a given L2 token.\\n */\\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(0, 0, 1)\\n CrossDomainEnabled(address(0))\\n {\\n initialize(_messenger, _otherBridge);\\n }\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n function initialize(address _messenger, address _otherBridge) public initializer {\\n messenger = _messenger;\\n otherBridge = _otherBridge;\\n\\n // Initialize upgradable OZ contracts\\n __Ownable_init();\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to the caller's account on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function bridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n // Modifier requiring sender to be EOA. This check could be bypassed by a malicious\\n // contract via initcode, but it takes care of the user error we want to avoid.\\n require(!Address.isContract(msg.sender), \\\"L1ERC721Bridge: account is not externally owned\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n msg.sender,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to some recipient's account on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function bridgeERC721To(\\n address _localToken,\\n address _remoteToken,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n _to,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /*************************\\n * Cross-chain Functions *\\n *************************/\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyFromCrossDomainAccount(otherBridge) {\\n // Checks that the L1/L2 token pair has a token ID that is escrowed in the L1 Bridge\\n require(\\n deposits[_localToken][_remoteToken][_tokenId] == true,\\n \\\"Token ID is not escrowed in the L1 Bridge\\\"\\n );\\n\\n deposits[_localToken][_remoteToken][_tokenId] = false;\\n\\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the withdrawer\\n // slither-disable-next-line reentrancy-events\\n IERC721(_localToken).transferFrom(address(this), _to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @notice Internal function for initiating a token bridge to the other domain.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _from Address of the sender on this domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal {\\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\\n bytes memory message = abi.encodeWithSelector(\\n L2ERC721Bridge.finalizeBridgeERC721.selector,\\n _remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Lock token into bridge\\n deposits[_localToken][_remoteToken][_tokenId] = true;\\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\\n\\n // Send calldata into L2\\n sendCrossDomainMessage(otherBridge, _minGasLimit, message);\\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0x6eb7efcb31944c40f6ceb1536d1928e88092339dd010ae137fa6934ba5dd47a7\",\"license\":\"MIT\"},\"contracts/L2/messaging/L2ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport {\\n CrossDomainEnabled\\n} from \\\"@eth-optimism/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport { ERC165Checker } from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { L1ERC721Bridge } from \\\"../../L1/messaging/L1ERC721Bridge.sol\\\";\\nimport { IOptimismMintableERC721 } from \\\"../../universal/op-erc721/IOptimismMintableERC721.sol\\\";\\nimport { Semver } from \\\"../../universal/Semver.sol\\\";\\n\\n/**\\n * @title L2ERC721Bridge\\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens between Optimism and Ethereum. This contract\\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\\n * This contract also acts as a burner for tokens being withdrawn.\\n */\\ncontract L2ERC721Bridge is Semver, CrossDomainEnabled, OwnableUpgradeable {\\n /**\\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeInitiated(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFinalized(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network fails.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFailed(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Address of the bridge on the other network.\\n */\\n address public otherBridge;\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(0, 0, 1)\\n CrossDomainEnabled(address(0))\\n {\\n initialize(_messenger, _otherBridge);\\n }\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n function initialize(address _messenger, address _otherBridge) public initializer {\\n messenger = _messenger;\\n otherBridge = _otherBridge;\\n\\n // Initialize upgradable OZ contracts\\n __Ownable_init();\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to the caller's account on L1.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function bridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n // Modifier requiring sender to be EOA. This check could be bypassed by a malicious\\n // contract via initcode, but it takes care of the user error we want to avoid.\\n require(!Address.isContract(msg.sender), \\\"L2ERC721Bridge: account is not externally owned\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n msg.sender,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to some recipient's account on L1.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function bridgeERC721To(\\n address _localToken,\\n address _remoteToken,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n _to,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyFromCrossDomainAccount(otherBridge) {\\n // Check the target token is compliant and verify the deposited token on L1 matches the L2\\n // deposited token representation.\\n if (\\n // slither-disable-next-line reentrancy-events\\n ERC165Checker.supportsInterface(\\n _localToken,\\n type(IOptimismMintableERC721).interfaceId\\n ) && _remoteToken == IOptimismMintableERC721(_localToken).remoteToken()\\n ) {\\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\\n // on L2.\\n // slither-disable-next-line reentrancy-events\\n IOptimismMintableERC721(_localToken).mint(_to, _tokenId);\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n } else {\\n // Either the L2 token which is being deposited-into disagrees about the correct address\\n // of its L1 token, or does not support the correct interface.\\n // This should only happen if there is a malicious L2 token, or if a user somehow\\n // specified the wrong L2 token address to deposit into.\\n // In either case, we stop the process here and construct a withdrawal\\n // message so that users can get their NFT out in some cases.\\n // There is no way to prevent malicious token contracts altogether, but this does limit\\n // user error and mitigate some forms of malicious contract behavior.\\n bytes memory message = abi.encodeWithSelector(\\n L1ERC721Bridge.finalizeBridgeERC721.selector,\\n _remoteToken,\\n _localToken,\\n _to, // switched the _to and _from here to bounce back the deposit to the sender\\n _from,\\n _tokenId,\\n _extraData\\n );\\n\\n // Send message up to L1 bridge\\n // slither-disable-next-line reentrancy-events\\n sendCrossDomainMessage(otherBridge, 0, message);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFailed(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n }\\n\\n /**\\n * @notice Internal function for initiating a token bridge to the other domain.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _from Address of the sender on this domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal {\\n // Check that the withdrawal is being initiated by the NFT owner\\n require(\\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\\n \\\"Withdrawal is not being initiated by NFT owner\\\"\\n );\\n\\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\\n // usage\\n // slither-disable-next-line reentrancy-events\\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\\n\\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\\n // slither-disable-next-line reentrancy-events\\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\\n require(\\n remoteToken == _remoteToken,\\n \\\"L2ERC721Bridge: remote token does not match given value\\\"\\n );\\n\\n bytes memory message = abi.encodeWithSelector(\\n L1ERC721Bridge.finalizeBridgeERC721.selector,\\n remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Send message to L1 bridge\\n // slither-disable-next-line reentrancy-events\\n sendCrossDomainMessage(otherBridge, _minGasLimit, message);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0xc03d61745dc6c8ddaae46667c8d092121847a7b6d9c9381a47cf1a5d75ba47f4\",\"license\":\"MIT\"},\"contracts/universal/Semver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Semver\\n * @notice Semver is a simple contract for managing contract versions.\\n */\\ncontract Semver {\\n /**\\n * @notice Contract version number (major).\\n */\\n uint256 public immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 public immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\n uint256 public immutable PATCH_VERSION;\\n\\n /**\\n * @param _major Version number (major).\\n * @param _minor Version number (minor).\\n * @param _patch Version number (patch).\\n */\\n constructor(\\n uint256 _major,\\n uint256 _minor,\\n uint256 _patch\\n ) {\\n MAJOR_VERSION = _major;\\n MINOR_VERSION = _minor;\\n PATCH_VERSION = _patch;\\n }\\n}\\n\",\"keccak256\":\"0x3a1b68a00fab786f42cc163b59fa8689ca3a2eee46114f3543e1f2ece1f78abb\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/IOptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport {\\n IERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\\\";\\n\\n/**\\n * @title IOptimismMintableERC721\\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\\n */\\ninterface IOptimismMintableERC721 is IERC721Enumerable {\\n /**\\n * @notice Emitted when a token is minted.\\n *\\n * @param account Address of the account the token was minted to.\\n * @param tokenId Token ID of the minted token.\\n */\\n event Mint(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Emitted when a token is burned.\\n *\\n * @param account Address of the account the token was burned from.\\n * @param tokenId Token ID of the burned token.\\n */\\n event Burn(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Chain ID of the chain where the remote token is deployed.\\n */\\n function remoteChainId() external returns (uint256);\\n\\n /**\\n * @notice Address of the token on the remote domain.\\n */\\n function remoteToken() external returns (address);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n function bridge() external returns (address);\\n\\n /**\\n * @notice Mints some token ID for a user.\\n *\\n * @param _to Address of the user to mint the token for.\\n * @param _tokenId Token ID to mint.\\n */\\n function mint(address _to, uint256 _tokenId) external;\\n\\n /**\\n * @notice Burns a token ID from a user.\\n *\\n * @param _from Address of the user to burn the token from.\\n * @param _tokenId Token ID to burn.\\n */\\n function burn(address _from, uint256 _tokenId) external;\\n}\\n\",\"keccak256\":\"0xad2e31bc9a8456a2f604749b0acc3f8882ff8c984f4d842b9e284dd1947439f3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b5060405162001d8e38038062001d8e83398101604081905262000034916200038a565b6000608081905260a0819052600160c05280546001600160a01b03191690556200005f828262000067565b5050620003c2565b60006200007560016200011a565b9050801562000092576000805460ff60a81b1916600160a81b1790555b600080546001600160a01b038086166001600160a01b0319928316179092556065805492851692909116919091179055620000cc62000244565b801562000115576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60008054600160a81b900460ff1615620001b5578160ff1660011480156200015557506200015330620002ae60201b62000ae31760201c565b155b620001ad5760405162461bcd60e51b815260206004820152602e602482015260008051602062001d4e83398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b506000919050565b60005460ff808416600160a01b90920416106200021b5760405162461bcd60e51b815260206004820152602e602482015260008051602062001d4e83398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620001a4565b506000805460ff909216600160a01b0260ff60a01b19909216919091179055600190565b919050565b600054600160a81b900460ff16620002a25760405162461bcd60e51b815260206004820152602b602482015260008051602062001d6e83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620001a4565b620002ac620002bd565b565b6001600160a01b03163b151590565b600054600160a81b900460ff166200031b5760405162461bcd60e51b815260206004820152602b602482015260008051602062001d6e83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620001a4565b620002ac33603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200023f57600080fd5b600080604083850312156200039e57600080fd5b620003a98362000372565b9150620003b96020840162000372565b90509250929050565b60805160a05160c05161195c620003f26000396000610150015260006101f10152600061022b015261195c6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063c8b915311161005b578063c8b91531146101ec578063f2fde38b14610213578063f786becd1461022657600080fd5b80638da5cb5b1461019b578063aa557452146101b9578063c89701a2146101cc57600080fd5b80636bf2606a116100b25780636bf2606a1461014b578063715018a614610180578063761f44931461018857600080fd5b80633687011a146100d95780633cb747bf146100ee578063485cc95514610138575b600080fd5b6100ec6100e7366004611554565b61024d565b005b60005461010e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100ec6101463660046115d7565b6102df565b6101727f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161012f565b6100ec6103f9565b6100ec610196366004611610565b61046c565b60335473ffffffffffffffffffffffffffffffffffffffff1661010e565b6100ec6101c73660046116a8565b6109ce565b60655461010e9073ffffffffffffffffffffffffffffffffffffffff1681565b6101727f000000000000000000000000000000000000000000000000000000000000000081565b6100ec61022136600461171f565b6109e7565b6101727f000000000000000000000000000000000000000000000000000000000000000081565b333b156102c75760405162461bcd60e51b815260206004820152602f60248201527f4c324552433732314272696467653a206163636f756e74206973206e6f74206560448201527f787465726e616c6c79206f776e6564000000000000000000000000000000000060648201526084015b60405180910390fd5b6102d78686333388888888610aff565b505050505050565b60006102eb6001610f43565b9050801561033457600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b6000805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560658054928516929091169190911790556103916110de565b80156103f457600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146104605760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102be565b61046a6000611177565b565b60655473ffffffffffffffffffffffffffffffffffffffff166104a460005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105445760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e7469636174656400000000000000000000000000000000000060648201526084016102be565b8073ffffffffffffffffffffffffffffffffffffffff1661057a60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156105bf57600080fd5b505afa1580156105d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f79190611743565b73ffffffffffffffffffffffffffffffffffffffff16146106805760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d6573736167650000000000000000000000000000000060648201526084016102be565b6106aa887f051e4975000000000000000000000000000000000000000000000000000000006111ee565b801561076057508773ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106f957600080fd5b505af115801561070d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107319190611743565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16145b15610874576040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690528916906340c10f1990604401600060405180830381600087803b1580156107d557600080fd5b505af11580156107e9573d6000803e3d6000fd5b505050508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8888888860405161086794939291906117a9565b60405180910390a46109c4565b600063761f449360e01b888a888a89898960405160240161089b97969594939291906117df565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526065549091506109409073ffffffffffffffffffffffffffffffffffffffff16600083611213565b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167f978c2c8d9b61339a8746e639110c2ea8fd38828e11965179b1fdf6c17b2636c8898989896040516109ba94939291906117a9565b60405180910390a4505b5050505050505050565b6109de8787338888888888610aff565b50505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610a4e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102be565b73ffffffffffffffffffffffffffffffffffffffff8116610ad75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102be565b610ae081611177565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e9060240160206040518083038186803b158015610b6557600080fd5b505afa158015610b79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9d9190611743565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610c3d5760405162461bcd60e51b815260206004820152602e60248201527f5769746864726177616c206973206e6f74206265696e6720696e69746961746560448201527f64206279204e4654206f776e657200000000000000000000000000000000000060648201526084016102be565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201869052891690639dc29fac90604401600060405180830381600087803b158015610cad57600080fd5b505af1158015610cc1573d6000803e3d6000fd5b5050505060008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d0f57600080fd5b505af1158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190611743565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610dea5760405162461bcd60e51b815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c756500000000000000000060648201526084016102be565b600063761f449360e01b828b8a8a8a8989604051602401610e1197969594939291906117df565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152606554909150610eb59073ffffffffffffffffffffffffffffffffffffffff168683611213565b8773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610f2f94939291906117a9565b60405180910390a450505050505050505050565b600080547501000000000000000000000000000000000000000000900460ff1615610ff4578160ff166001148015610f7a5750303b155b610fec5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102be565b506000919050565b60005460ff8084167401000000000000000000000000000000000000000090920416106110895760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102be565b506000805460ff90921674010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055600190565b919050565b6000547501000000000000000000000000000000000000000000900460ff1661116f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102be565b61046a61129b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006111f983611335565b801561120a575061120a8383611399565b90505b92915050565b6000546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b9061126d9086908590879060040161186c565b600060405180830381600087803b15801561128757600080fd5b505af11580156109de573d6000803e3d6000fd5b6000547501000000000000000000000000000000000000000000900460ff1661132c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102be565b61046a33611177565b6000611361827f01ffc9a700000000000000000000000000000000000000000000000000000000611399565b801561120d5750611392827fffffffff00000000000000000000000000000000000000000000000000000000611399565b1592915050565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a7000000000000000000000000000000000000000000000000000000001790529051600091908290819073ffffffffffffffffffffffffffffffffffffffff871690617530906114539086906118e8565b6000604051808303818686fa925050503d806000811461148f576040519150601f19603f3d011682016040523d82523d6000602084013e611494565b606091505b50915091506020815110156114af576000935050505061120d565b8180156114cb5750808060200190518101906114cb9190611904565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ae057600080fd5b803563ffffffff811681146110d957600080fd5b60008083601f84011261151d57600080fd5b50813567ffffffffffffffff81111561153557600080fd5b60208301915083602082850101111561154d57600080fd5b9250929050565b60008060008060008060a0878903121561156d57600080fd5b8635611578816114d5565b95506020870135611588816114d5565b94506040870135935061159d606088016114f7565b9250608087013567ffffffffffffffff8111156115b957600080fd5b6115c589828a0161150b565b979a9699509497509295939492505050565b600080604083850312156115ea57600080fd5b82356115f5816114d5565b91506020830135611605816114d5565b809150509250929050565b600080600080600080600060c0888a03121561162b57600080fd5b8735611636816114d5565b96506020880135611646816114d5565b95506040880135611656816114d5565b94506060880135611666816114d5565b93506080880135925060a088013567ffffffffffffffff81111561168957600080fd5b6116958a828b0161150b565b989b979a50959850939692959293505050565b600080600080600080600060c0888a0312156116c357600080fd5b87356116ce816114d5565b965060208801356116de816114d5565b955060408801356116ee816114d5565b945060608801359350611703608089016114f7565b925060a088013567ffffffffffffffff81111561168957600080fd5b60006020828403121561173157600080fd5b813561173c816114d5565b9392505050565b60006020828403121561175557600080fd5b815161173c816114d5565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006114cb606083018486611760565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261182f60c083018486611760565b9998505050505050505050565b60005b8381101561185757818101518382015260200161183f565b83811115611866576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600083518060608401526118a781608085016020880161183c565b63ffffffff93909316604083015250601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160160800192915050565b600082516118fa81846020870161183c565b9190910192915050565b60006020828403121561191657600080fd5b8151801515811461173c57600080fdfea264697066735822122060533a937961dd794625389c057b673dfdde321be6b618769fbc945c64a2be5064736f6c63430008090033496e697469616c697a61626c653a20636f6e747261637420697320616c726561496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063c8b915311161005b578063c8b91531146101ec578063f2fde38b14610213578063f786becd1461022657600080fd5b80638da5cb5b1461019b578063aa557452146101b9578063c89701a2146101cc57600080fd5b80636bf2606a116100b25780636bf2606a1461014b578063715018a614610180578063761f44931461018857600080fd5b80633687011a146100d95780633cb747bf146100ee578063485cc95514610138575b600080fd5b6100ec6100e7366004611554565b61024d565b005b60005461010e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100ec6101463660046115d7565b6102df565b6101727f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161012f565b6100ec6103f9565b6100ec610196366004611610565b61046c565b60335473ffffffffffffffffffffffffffffffffffffffff1661010e565b6100ec6101c73660046116a8565b6109ce565b60655461010e9073ffffffffffffffffffffffffffffffffffffffff1681565b6101727f000000000000000000000000000000000000000000000000000000000000000081565b6100ec61022136600461171f565b6109e7565b6101727f000000000000000000000000000000000000000000000000000000000000000081565b333b156102c75760405162461bcd60e51b815260206004820152602f60248201527f4c324552433732314272696467653a206163636f756e74206973206e6f74206560448201527f787465726e616c6c79206f776e6564000000000000000000000000000000000060648201526084015b60405180910390fd5b6102d78686333388888888610aff565b505050505050565b60006102eb6001610f43565b9050801561033457600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b6000805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560658054928516929091169190911790556103916110de565b80156103f457600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146104605760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102be565b61046a6000611177565b565b60655473ffffffffffffffffffffffffffffffffffffffff166104a460005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105445760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e7469636174656400000000000000000000000000000000000060648201526084016102be565b8073ffffffffffffffffffffffffffffffffffffffff1661057a60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156105bf57600080fd5b505afa1580156105d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f79190611743565b73ffffffffffffffffffffffffffffffffffffffff16146106805760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d6573736167650000000000000000000000000000000060648201526084016102be565b6106aa887f051e4975000000000000000000000000000000000000000000000000000000006111ee565b801561076057508773ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106f957600080fd5b505af115801561070d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107319190611743565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16145b15610874576040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690528916906340c10f1990604401600060405180830381600087803b1580156107d557600080fd5b505af11580156107e9573d6000803e3d6000fd5b505050508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8888888860405161086794939291906117a9565b60405180910390a46109c4565b600063761f449360e01b888a888a89898960405160240161089b97969594939291906117df565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526065549091506109409073ffffffffffffffffffffffffffffffffffffffff16600083611213565b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167f978c2c8d9b61339a8746e639110c2ea8fd38828e11965179b1fdf6c17b2636c8898989896040516109ba94939291906117a9565b60405180910390a4505b5050505050505050565b6109de8787338888888888610aff565b50505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610a4e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102be565b73ffffffffffffffffffffffffffffffffffffffff8116610ad75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102be565b610ae081611177565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e9060240160206040518083038186803b158015610b6557600080fd5b505afa158015610b79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9d9190611743565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610c3d5760405162461bcd60e51b815260206004820152602e60248201527f5769746864726177616c206973206e6f74206265696e6720696e69746961746560448201527f64206279204e4654206f776e657200000000000000000000000000000000000060648201526084016102be565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201869052891690639dc29fac90604401600060405180830381600087803b158015610cad57600080fd5b505af1158015610cc1573d6000803e3d6000fd5b5050505060008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d0f57600080fd5b505af1158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190611743565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610dea5760405162461bcd60e51b815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c756500000000000000000060648201526084016102be565b600063761f449360e01b828b8a8a8a8989604051602401610e1197969594939291906117df565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152606554909150610eb59073ffffffffffffffffffffffffffffffffffffffff168683611213565b8773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610f2f94939291906117a9565b60405180910390a450505050505050505050565b600080547501000000000000000000000000000000000000000000900460ff1615610ff4578160ff166001148015610f7a5750303b155b610fec5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102be565b506000919050565b60005460ff8084167401000000000000000000000000000000000000000090920416106110895760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102be565b506000805460ff90921674010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055600190565b919050565b6000547501000000000000000000000000000000000000000000900460ff1661116f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102be565b61046a61129b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006111f983611335565b801561120a575061120a8383611399565b90505b92915050565b6000546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b9061126d9086908590879060040161186c565b600060405180830381600087803b15801561128757600080fd5b505af11580156109de573d6000803e3d6000fd5b6000547501000000000000000000000000000000000000000000900460ff1661132c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102be565b61046a33611177565b6000611361827f01ffc9a700000000000000000000000000000000000000000000000000000000611399565b801561120d5750611392827fffffffff00000000000000000000000000000000000000000000000000000000611399565b1592915050565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a7000000000000000000000000000000000000000000000000000000001790529051600091908290819073ffffffffffffffffffffffffffffffffffffffff871690617530906114539086906118e8565b6000604051808303818686fa925050503d806000811461148f576040519150601f19603f3d011682016040523d82523d6000602084013e611494565b606091505b50915091506020815110156114af576000935050505061120d565b8180156114cb5750808060200190518101906114cb9190611904565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ae057600080fd5b803563ffffffff811681146110d957600080fd5b60008083601f84011261151d57600080fd5b50813567ffffffffffffffff81111561153557600080fd5b60208301915083602082850101111561154d57600080fd5b9250929050565b60008060008060008060a0878903121561156d57600080fd5b8635611578816114d5565b95506020870135611588816114d5565b94506040870135935061159d606088016114f7565b9250608087013567ffffffffffffffff8111156115b957600080fd5b6115c589828a0161150b565b979a9699509497509295939492505050565b600080604083850312156115ea57600080fd5b82356115f5816114d5565b91506020830135611605816114d5565b809150509250929050565b600080600080600080600060c0888a03121561162b57600080fd5b8735611636816114d5565b96506020880135611646816114d5565b95506040880135611656816114d5565b94506060880135611666816114d5565b93506080880135925060a088013567ffffffffffffffff81111561168957600080fd5b6116958a828b0161150b565b989b979a50959850939692959293505050565b600080600080600080600060c0888a0312156116c357600080fd5b87356116ce816114d5565b965060208801356116de816114d5565b955060408801356116ee816114d5565b945060608801359350611703608089016114f7565b925060a088013567ffffffffffffffff81111561168957600080fd5b60006020828403121561173157600080fd5b813561173c816114d5565b9392505050565b60006020828403121561175557600080fd5b815161173c816114d5565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006114cb606083018486611760565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261182f60c083018486611760565b9998505050505050505050565b60005b8381101561185757818101518382015260200161183f565b83811115611866576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600083518060608401526118a781608085016020880161183c565b63ffffffff93909316604083015250601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160160800192915050565b600082516118fa81846020870161183c565b9190910192915050565b60006020828403121561191657600080fd5b8151801515811461173c57600080fdfea264697066735822122060533a937961dd794625389c057b673dfdde321be6b618769fbc945c64a2be5064736f6c63430008090033", - "devdoc": { - "events": { - "ERC721BridgeFailed(address,address,address,address,uint256,bytes)": { - "params": { - "extraData": "Extra data for use on the client-side.", - "from": "Address that initiated bridging action.", - "localToken": "Address of the token on this domain.", - "remoteToken": "Address of the token on the remote domain.", - "to": "Address to receive the token.", - "tokenId": "ID of the specific token deposited." - } - }, - "ERC721BridgeFinalized(address,address,address,address,uint256,bytes)": { - "params": { - "extraData": "Extra data for use on the client-side.", - "from": "Address that initiated bridging action.", - "localToken": "Address of the token on this domain.", - "remoteToken": "Address of the token on the remote domain.", - "to": "Address to receive the token.", - "tokenId": "ID of the specific token deposited." - } - }, - "ERC721BridgeInitiated(address,address,address,address,uint256,bytes)": { - "params": { - "extraData": "Extra data for use on the client-side.", - "from": "Address that initiated bridging action.", - "localToken": "Address of the token on this domain.", - "remoteToken": "Address of the token on the remote domain.", - "to": "Address to receive the token.", - "tokenId": "ID of the specific token deposited." - } - } - }, - "kind": "dev", - "methods": { - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to L1. Data supplied here will not be used to execute any code on L1 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 L1. Data supplied here will not be used to execute any code on L1 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.", - "_otherBridge": "Address of the ERC721 bridge on the other network." - } - }, - "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { - "params": { - "_extraData": "Optional data to forward to L1. Data supplied here will not be used to execute any code on L1 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,address)": { - "params": { - "_messenger": "Address of the CrossDomainMessenger on this network.", - "_otherBridge": "Address of the ERC721 bridge on the other network." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "title": "L2ERC721Bridge", - "version": 1 - }, - "userdoc": { - "events": { - "ERC721BridgeFailed(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC721 bridge from the other network fails." - }, - "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." - } - }, - "kind": "user", - "methods": { - "MAJOR_VERSION()": { - "notice": "Contract version number (major)." - }, - "MINOR_VERSION()": { - "notice": "Contract version number (minor)." - }, - "PATCH_VERSION()": { - "notice": "Contract version number (patch)." - }, - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to the caller's account on L1." - }, - "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to some recipient's account on L1." - }, - "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." - }, - "otherBridge()": { - "notice": "Address of the bridge on the other network." - } - }, - "notice": "The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to make it possible to transfer ERC721 tokens between Optimism and Ethereum. This contract acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge. This contract also acts as a burner for tokens being withdrawn.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1119, - "contract": "contracts/L2/messaging/L2ERC721Bridge.sol:L2ERC721Bridge", - "label": "messenger", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 1361, - "contract": "contracts/L2/messaging/L2ERC721Bridge.sol:L2ERC721Bridge", - "label": "_initialized", - "offset": 20, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 1364, - "contract": "contracts/L2/messaging/L2ERC721Bridge.sol:L2ERC721Bridge", - "label": "_initializing", - "offset": 21, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 1780, - "contract": "contracts/L2/messaging/L2ERC721Bridge.sol:L2ERC721Bridge", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 1241, - "contract": "contracts/L2/messaging/L2ERC721Bridge.sol:L2ERC721Bridge", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 1353, - "contract": "contracts/L2/messaging/L2ERC721Bridge.sol:L2ERC721Bridge", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 5434, - "contract": "contracts/L2/messaging/L2ERC721Bridge.sol:L2ERC721Bridge", - "label": "otherBridge", - "offset": 0, - "slot": "101", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-kovan/L2ERC721BridgeProxy.json b/packages/contracts-periphery/deployments/optimism-kovan/L2ERC721BridgeProxy.json deleted file mode 100644 index 1e44ff0cd4208..0000000000000 --- a/packages/contracts-periphery/deployments/optimism-kovan/L2ERC721BridgeProxy.json +++ /dev/null @@ -1,224 +0,0 @@ -{ - "address": "0x67997A4F970aD1c91B911C4d7A6598aF2cFb1F56", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_admin", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "admin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_admin", - "type": "address" - } - ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "implementation", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_implementation", - "type": "address" - } - ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_implementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } - ], - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "9bf33bb642648b258386a9c465b5d346", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"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\"}}},\"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 owner. The owner has the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"The address of the implementation contract\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"The calldata to delegatecall the new implementation with\",\"_implementation\":\"The address of the implementation contract\"}}},\"title\":\"Proxy\",\"version\":1},\"userdoc\":{\"events\":{\"AdminChanged(address,address)\":{\"notice\":\"An event that is emitted each time the owner is upgraded. This event is part of the EIP 1967 spec.\"},\"Upgraded(address)\":{\"notice\":\"An event that is emitted each time the implementation is changed. This event is part of the EIP 1967 spec.\"}},\"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\":\"set the initial owner during contract deployment. The owner is stored at the eip1967 owner storage slot so that storage collision with the implementation is not possible.\"},\"implementation()\":{\"notice\":\"Queries the implementation address.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at this address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. This is useful to ensure atomic `initialize()` based upgrades.\"}},\"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 offchain simulation.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Proxy\\n * @notice Proxy is a transparent proxy that passes through the call\\n * if the caller is the owner or if the caller is `address(0)`,\\n * meaning that the call originated from an offchain simulation.\\n */\\ncontract Proxy {\\n /**\\n * @notice An event that is emitted each time the implementation is changed.\\n * This event is part of the EIP 1967 spec.\\n *\\n * @param implementation The address of the implementation contract\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @notice An event that is emitted each time the owner is upgraded.\\n * This event is part of the EIP 1967 spec.\\n *\\n * @param previousAdmin The previous owner of the contract\\n * @param newAdmin The new owner of the contract\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @notice The storage slot that holds the address of the implementation.\\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n */\\n bytes32 internal constant IMPLEMENTATION_KEY =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @notice The storage slot that holds the address of the owner.\\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n */\\n bytes32 internal constant OWNER_KEY =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @notice set the initial owner during contract deployment. The\\n * owner is stored at the eip1967 owner storage slot so that\\n * storage collision with the implementation is not possible.\\n *\\n * @param _admin Address of the initial contract owner. The owner has\\n * the ability to access the transparent proxy interface.\\n */\\n constructor(address _admin) {\\n _changeAdmin(_admin);\\n }\\n\\n // slither-disable-next-line locked-ether\\n fallback() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n /**\\n * @notice A modifier that reverts if not called by the owner\\n * or by `address(0)` to allow `eth_call` to interact\\n * with the proxy without needing to use low level storage\\n * inspection. It is assumed that nobody controls the private\\n * key for `address(0)`.\\n */\\n modifier proxyCallIfNotAdmin() {\\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\\n _;\\n } else {\\n // This WILL halt the call frame on completion.\\n _doProxyCall();\\n }\\n }\\n\\n /**\\n * @notice Set the implementation contract address. The code at this\\n * address will execute when this contract is called.\\n *\\n * @param _implementation The address of the implementation contract\\n */\\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\\n _setImplementation(_implementation);\\n }\\n\\n /**\\n * @notice Set the implementation and call a function in a single\\n * transaction. This is useful to ensure atomic `initialize()`\\n * based upgrades.\\n *\\n * @param _implementation The address of the implementation contract\\n * @param _data The calldata to delegatecall the new\\n * implementation with\\n */\\n function upgradeToAndCall(address _implementation, bytes calldata _data)\\n external\\n payable\\n proxyCallIfNotAdmin\\n returns (bytes memory)\\n {\\n _setImplementation(_implementation);\\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\\n require(success);\\n return returndata;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\\n _changeAdmin(_admin);\\n }\\n\\n /**\\n * @notice Gets the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function admin() external proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() external proxyCallIfNotAdmin returns (address) {\\n return _getImplementation();\\n }\\n\\n /**\\n * @notice Sets the implementation address.\\n *\\n * @param _implementation New implementation address.\\n */\\n function _setImplementation(address _implementation) internal {\\n assembly {\\n sstore(IMPLEMENTATION_KEY, _implementation)\\n }\\n emit Upgraded(_implementation);\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n address implementation;\\n assembly {\\n implementation := sload(IMPLEMENTATION_KEY)\\n }\\n return implementation;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function _changeAdmin(address _admin) internal {\\n address previous = _getAdmin();\\n assembly {\\n sstore(OWNER_KEY, _admin)\\n }\\n emit AdminChanged(previous, _admin);\\n }\\n\\n /**\\n * @notice Queries the owner of the proxy contract.\\n *\\n * @return owner address.\\n */\\n function _getAdmin() internal view returns (address) {\\n address owner;\\n assembly {\\n owner := sload(OWNER_KEY)\\n }\\n return owner;\\n }\\n\\n /**\\n * @notice Performs the proxy call via a delegatecall.\\n */\\n function _doProxyCall() internal {\\n address implementation = _getImplementation();\\n\\n require(implementation != address(0), \\\"Proxy: implementation not initialized\\\");\\n\\n assembly {\\n // Copy calldata into memory at 0x0....calldatasize.\\n calldatacopy(0x0, 0x0, calldatasize())\\n\\n // Perform the delegatecall, make sure to pass all available gas.\\n let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)\\n\\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\\n // overwrite the calldata that we just copied into memory but that doesn't really\\n // matter because we'll be returning in a second anyway.\\n returndatacopy(0x0, 0x0, returndatasize())\\n\\n // Success == 0 means a revert. We'll revert too and pass the data up.\\n if iszero(success) {\\n revert(0x0, returndatasize())\\n }\\n\\n // Otherwise we'll just return and pass the data up.\\n return(0x0, returndatasize())\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2a6719fd9a11adf0efba0243e5c68d56b255296b84cc82bd39326c902e055077\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506040516108ac3803806108ac83398101604081905261002f916100b2565b6100388161003e565b506100e2565b600061005660008051602061088c8339815191525490565b60008051602061088c833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b61079b806100f16000396000f3fe60806040526004361061005a5760003560e01c80635c60da1b116100435780635c60da1b146100ad5780638f283970146100e7578063f851a440146101075761005a565b80633659cfe6146100645780634f1ef28614610084575b61006261011c565b005b34801561007057600080fd5b5061006261007f366004610644565b610212565b61009761009236600461065f565b610284565b6040516100a491906106e2565b60405180910390f35b3480156100b957600080fd5b506100c2610384565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a4565b3480156100f357600080fd5b50610062610102366004610644565b61041b565b34801561011357600080fd5b506100c2610482565b60006101467f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166101ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a6564000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b3660008037600080366000845af43d6000803e8061020c573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061026b575033155b1561027c576102798161050e565b50565b61027961011c565b60606102ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102e5575033155b15610375576102f38461050e565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161031d929190610755565b600060405180830381855af49150503d8060008114610358576040519150601f19603f3d011682016040523d82523d6000602084013e61035d565b606091505b50915091508161036c57600080fd5b915061037d9050565b61037d61011c565b9392505050565b60006103ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103e5575033155b1561041057507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b61041861011c565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610474575033155b1561027c5761027981610576565b60006104ac7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104e3575033155b1561041057507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006105a07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461063f57600080fd5b919050565b60006020828403121561065657600080fd5b61037d8261061b565b60008060006040848603121561067457600080fd5b61067d8461061b565b9250602084013567ffffffffffffffff8082111561069a57600080fd5b818601915086601f8301126106ae57600080fd5b8135818111156106bd57600080fd5b8760208285010111156106cf57600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b8181101561070f578581018301518582016040015282016106f3565b81811115610721576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea264697066735822122002cf23bcc281eec5c701686c2374a3972d766187632ccdd7ca1fe3d13cb4866264736f6c63430008090033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005a5760003560e01c80635c60da1b116100435780635c60da1b146100ad5780638f283970146100e7578063f851a440146101075761005a565b80633659cfe6146100645780634f1ef28614610084575b61006261011c565b005b34801561007057600080fd5b5061006261007f366004610644565b610212565b61009761009236600461065f565b610284565b6040516100a491906106e2565b60405180910390f35b3480156100b957600080fd5b506100c2610384565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a4565b3480156100f357600080fd5b50610062610102366004610644565b61041b565b34801561011357600080fd5b506100c2610482565b60006101467f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166101ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a6564000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b3660008037600080366000845af43d6000803e8061020c573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061026b575033155b1561027c576102798161050e565b50565b61027961011c565b60606102ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102e5575033155b15610375576102f38461050e565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161031d929190610755565b600060405180830381855af49150503d8060008114610358576040519150601f19603f3d011682016040523d82523d6000602084013e61035d565b606091505b50915091508161036c57600080fd5b915061037d9050565b61037d61011c565b9392505050565b60006103ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103e5575033155b1561041057507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b61041861011c565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610474575033155b1561027c5761027981610576565b60006104ac7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104e3575033155b1561041057507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006105a07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461063f57600080fd5b919050565b60006020828403121561065657600080fd5b61037d8261061b565b60008060006040848603121561067457600080fd5b61067d8461061b565b9250602084013567ffffffffffffffff8082111561069a57600080fd5b818601915086601f8301126106ae57600080fd5b8135818111156106bd57600080fd5b8760208285010111156106cf57600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b8181101561070f578581018301518582016040015282016106f3565b81811115610721576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea264697066735822122002cf23bcc281eec5c701686c2374a3972d766187632ccdd7ca1fe3d13cb4866264736f6c63430008090033", - "devdoc": { - "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" - } - } - }, - "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 owner. The owner has the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "The address of the implementation contract" - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "The calldata to delegatecall the new implementation with", - "_implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy", - "version": 1 - }, - "userdoc": { - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP 1967 spec." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP 1967 spec." - } - }, - "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": "set the initial owner during contract deployment. The owner is stored at the eip1967 owner storage slot so that storage collision with the implementation is not possible." - }, - "implementation()": { - "notice": "Queries the implementation address." - }, - "upgradeTo(address)": { - "notice": "Set the implementation contract address. The code at this address will execute when this contract is called." - }, - "upgradeToAndCall(address,bytes)": { - "notice": "Set the implementation and call a function in a single transaction. This is useful to ensure atomic `initialize()` based upgrades." - } - }, - "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 offchain simulation.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-kovan/OptimismMintableERC721Factory.json b/packages/contracts-periphery/deployments/optimism-kovan/OptimismMintableERC721Factory.json deleted file mode 100644 index 61b56a506fb49..0000000000000 --- a/packages/contracts-periphery/deployments/optimism-kovan/OptimismMintableERC721Factory.json +++ /dev/null @@ -1,468 +0,0 @@ -{ - "address": "0x83192085ffDB8419e6f3876041110c3bb0f0fb20", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_bridge", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_remoteChainId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - } - ], - "name": "OptimismMintableERC721Created", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "MAJOR_VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MINOR_VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PATCH_VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - } - ], - "name": "createStandardOptimismMintableERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_bridge", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_remoteChainId", - "type": "uint256" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "isStandardOptimismMintableERC721", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "remoteChainId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x05e3a2ed8c43687f26acb9c5d8c2ef826b2b762ea586d878179eccc7daea5006", - "receipt": { - "to": null, - "from": "0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5", - "contractAddress": "0x83192085ffDB8419e6f3876041110c3bb0f0fb20", - "transactionIndex": 0, - "gasUsed": "3275400", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000080000000000000000000000000000080000000020000000000000000001000000000000000000400000000000000000000000000000000000000000000000000000000000000040010000000000000000000000000000020000000000000000000000000000000000000000000000000000000000010000000", - "blockHash": "0xde927f1a1fc56ba9a22707c622115f8882b66257a43d0872ed4eb88d28ffd54e", - "transactionHash": "0x05e3a2ed8c43687f26acb9c5d8c2ef826b2b762ea586d878179eccc7daea5006", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 4498535, - "transactionHash": "0x05e3a2ed8c43687f26acb9c5d8c2ef826b2b762ea586d878179eccc7daea5006", - "address": "0x83192085ffDB8419e6f3876041110c3bb0f0fb20", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000c37f6a6c4ab335e20d10f034b90386e2fb70bbf5" - ], - "data": "0x", - "logIndex": 0, - "blockHash": "0xde927f1a1fc56ba9a22707c622115f8882b66257a43d0872ed4eb88d28ffd54e" - }, - { - "transactionIndex": 0, - "blockNumber": 4498535, - "transactionHash": "0x05e3a2ed8c43687f26acb9c5d8c2ef826b2b762ea586d878179eccc7daea5006", - "address": "0x83192085ffDB8419e6f3876041110c3bb0f0fb20", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 1, - "blockHash": "0xde927f1a1fc56ba9a22707c622115f8882b66257a43d0872ed4eb88d28ffd54e" - } - ], - "blockNumber": 4498535, - "cumulativeGasUsed": "3275400", - "status": 1, - "byzantium": true - }, - "args": [ - "0x0000000000000000000000000000000000000000", - 0 - ], - "numDeployments": 4, - "solcInputHash": "c6fd6c61d1988656e270189e3651a1e1", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_remoteChainId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"OptimismMintableERC721Created\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAJOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PATCH_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createStandardOptimismMintableERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_remoteChainId\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isStandardOptimismMintableERC721\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"remoteChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"OptimismMintableERC721Created(address,address)\":{\"params\":{\"localToken\":\"Address of the token on the this domain.\",\"remoteToken\":\"Address of the token on the remote domain.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_bridge\":\"Address of the ERC721 bridge on this network.\"}},\"createStandardOptimismMintableERC721(address,string,string)\":{\"params\":{\"_name\":\"ERC721 name.\",\"_remoteToken\":\"Address of the corresponding token on the other domain.\",\"_symbol\":\"ERC721 symbol.\"}},\"initialize(address,uint256)\":{\"params\":{\"_bridge\":\"Address of the ERC721 bridge on this network.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"OptimismMintableERC721Factory\",\"version\":1},\"userdoc\":{\"events\":{\"OptimismMintableERC721Created(address,address)\":{\"notice\":\"Emitted whenever a new OptimismMintableERC721 contract is created.\"}},\"kind\":\"user\",\"methods\":{\"MAJOR_VERSION()\":{\"notice\":\"Contract version number (major).\"},\"MINOR_VERSION()\":{\"notice\":\"Contract version number (minor).\"},\"PATCH_VERSION()\":{\"notice\":\"Contract version number (patch).\"},\"bridge()\":{\"notice\":\"Address of the ERC721 bridge on this network.\"},\"createStandardOptimismMintableERC721(address,string,string)\":{\"notice\":\"Creates an instance of the standard ERC721.\"},\"initialize(address,uint256)\":{\"notice\":\"Initializes the factory.\"},\"isStandardOptimismMintableERC721(address)\":{\"notice\":\"Tracks addresses created by this factory.\"},\"remoteChainId()\":{\"notice\":\"Chain ID for the remote network.\"}},\"notice\":\"Factory contract for creating OptimismMintableERC721 contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-erc721/OptimismMintableERC721Factory.sol\":\"OptimismMintableERC721Factory\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x652fee292f698d8dba81bf287cb71f1682f6483b67ebe601a5f7387dcfc30b34\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = _setInitializedVersion(1);\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\\n * initialization step. This is essential to configure modules that are added through upgrades and that require\\n * initialization.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n */\\n modifier reinitializer(uint8 version) {\\n bool isTopLevelCall = _setInitializedVersion(version);\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(version);\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n */\\n function _disableInitializers() internal virtual {\\n _setInitializedVersion(type(uint8).max);\\n }\\n\\n function _setInitializedVersion(uint8 version) private returns (bool) {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\\n // of initializers, because in other contexts the contract may have been reentered.\\n if (_initializing) {\\n require(\\n version == 1 && !AddressUpgradeable.isContract(address(this)),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n return false;\\n } else {\\n require(_initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n return true;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7454006cccb737612b00104d2f606d728e2818b778e7e55542f063c614ce46ba\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55cf2bd9fc76704ddcdc19834cd288b7de00fc0f298a40ea16a954ae8991db2d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _owners[tokenId];\\n require(owner != address(0), \\\"ERC721: owner query for nonexistent token\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overridden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n _safeTransfer(from, to, tokenId, _data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _owners[tokenId] != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, _data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId);\\n\\n _balances[to] += 1;\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n\\n _afterTokenTransfer(address(0), to, tokenId);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n // Clear approvals\\n _approve(address(0), tokenId);\\n\\n _balances[owner] -= 1;\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n\\n _afterTokenTransfer(owner, address(0), tokenId);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId);\\n\\n // Clear approvals from the previous owner\\n _approve(address(0), tokenId);\\n\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n\\n _afterTokenTransfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits a {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits a {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(\\n address owner,\\n address operator,\\n bool approved\\n ) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param _data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n * transferred to `to`.\\n * - When `from` is zero, `tokenId` will be minted for `to`.\\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x921f012325281f7d81e29c53a13824cf6c2c5d77232065d0d4f3f912e97af6ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC721.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\n\\n/**\\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\\n * enumerability of all the token ids in the contract as well as all token ids owned by each\\n * account.\\n */\\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\\n // Mapping from owner to list of owned token IDs\\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\\n\\n // Mapping from token ID to index of the owner tokens list\\n mapping(uint256 => uint256) private _ownedTokensIndex;\\n\\n // Array with all token ids, used for enumeration\\n uint256[] private _allTokens;\\n\\n // Mapping from token id to position in the allTokens array\\n mapping(uint256 => uint256) private _allTokensIndex;\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n require(index < ERC721.balanceOf(owner), \\\"ERC721Enumerable: owner index out of bounds\\\");\\n return _ownedTokens[owner][index];\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _allTokens.length;\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-tokenByIndex}.\\n */\\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n require(index < ERC721Enumerable.totalSupply(), \\\"ERC721Enumerable: global index out of bounds\\\");\\n return _allTokens[index];\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n * transferred to `to`.\\n * - When `from` is zero, `tokenId` will be minted for `to`.\\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual override {\\n super._beforeTokenTransfer(from, to, tokenId);\\n\\n if (from == address(0)) {\\n _addTokenToAllTokensEnumeration(tokenId);\\n } else if (from != to) {\\n _removeTokenFromOwnerEnumeration(from, tokenId);\\n }\\n if (to == address(0)) {\\n _removeTokenFromAllTokensEnumeration(tokenId);\\n } else if (to != from) {\\n _addTokenToOwnerEnumeration(to, tokenId);\\n }\\n }\\n\\n /**\\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\\n * @param to address representing the new owner of the given token ID\\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\\n */\\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\\n uint256 length = ERC721.balanceOf(to);\\n _ownedTokens[to][length] = tokenId;\\n _ownedTokensIndex[tokenId] = length;\\n }\\n\\n /**\\n * @dev Private function to add a token to this extension's token tracking data structures.\\n * @param tokenId uint256 ID of the token to be added to the tokens list\\n */\\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\\n _allTokensIndex[tokenId] = _allTokens.length;\\n _allTokens.push(tokenId);\\n }\\n\\n /**\\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\\n * @param from address representing the previous owner of the given token ID\\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\\n */\\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\\n // then delete the last slot (swap and pop).\\n\\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\\n\\n // When the token to delete is the last token, the swap operation is unnecessary\\n if (tokenIndex != lastTokenIndex) {\\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\\n\\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\\n }\\n\\n // This also deletes the contents at the last position of the array\\n delete _ownedTokensIndex[tokenId];\\n delete _ownedTokens[from][lastTokenIndex];\\n }\\n\\n /**\\n * @dev Private function to remove a token from this extension's token tracking data structures.\\n * This has O(1) time complexity, but alters the order of the _allTokens array.\\n * @param tokenId uint256 ID of the token to be removed from the tokens list\\n */\\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\\n // then delete the last slot (swap and pop).\\n\\n uint256 lastTokenIndex = _allTokens.length - 1;\\n uint256 tokenIndex = _allTokensIndex[tokenId];\\n\\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\\n uint256 lastTokenId = _allTokens[lastTokenIndex];\\n\\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\\n\\n // This also deletes the contents at the last position of the array\\n delete _allTokensIndex[tokenId];\\n _allTokens.pop();\\n }\\n}\\n\",\"keccak256\":\"0x0a79511df8151b10b0a0004d6a76ad956582d32824af4c0f4886bdbdfe5746e5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/universal/Semver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Semver\\n * @notice Semver is a simple contract for managing contract versions.\\n */\\ncontract Semver {\\n /**\\n * @notice Contract version number (major).\\n */\\n uint256 public immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 public immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\n uint256 public immutable PATCH_VERSION;\\n\\n /**\\n * @param _major Version number (major).\\n * @param _minor Version number (minor).\\n * @param _patch Version number (patch).\\n */\\n constructor(\\n uint256 _major,\\n uint256 _minor,\\n uint256 _patch\\n ) {\\n MAJOR_VERSION = _major;\\n MINOR_VERSION = _minor;\\n PATCH_VERSION = _patch;\\n }\\n}\\n\",\"keccak256\":\"0x3a1b68a00fab786f42cc163b59fa8689ca3a2eee46114f3543e1f2ece1f78abb\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/IOptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport {\\n IERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\\\";\\n\\n/**\\n * @title IOptimismMintableERC721\\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\\n */\\ninterface IOptimismMintableERC721 is IERC721Enumerable {\\n /**\\n * @notice Emitted when a token is minted.\\n *\\n * @param account Address of the account the token was minted to.\\n * @param tokenId Token ID of the minted token.\\n */\\n event Mint(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Emitted when a token is burned.\\n *\\n * @param account Address of the account the token was burned from.\\n * @param tokenId Token ID of the burned token.\\n */\\n event Burn(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Chain ID of the chain where the remote token is deployed.\\n */\\n function remoteChainId() external returns (uint256);\\n\\n /**\\n * @notice Address of the token on the remote domain.\\n */\\n function remoteToken() external returns (address);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n function bridge() external returns (address);\\n\\n /**\\n * @notice Mints some token ID for a user.\\n *\\n * @param _to Address of the user to mint the token for.\\n * @param _tokenId Token ID to mint.\\n */\\n function mint(address _to, uint256 _tokenId) external;\\n\\n /**\\n * @notice Burns a token ID from a user.\\n *\\n * @param _from Address of the user to burn the token from.\\n * @param _tokenId Token ID to burn.\\n */\\n function burn(address _from, uint256 _tokenId) external;\\n}\\n\",\"keccak256\":\"0xad2e31bc9a8456a2f604749b0acc3f8882ff8c984f4d842b9e284dd1947439f3\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/OptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport {\\n ERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\\\";\\nimport { ERC721 } from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport { IERC165 } from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport { IOptimismMintableERC721 } from \\\"./IOptimismMintableERC721.sol\\\";\\n\\n/**\\n * @title OptimismMintableERC721\\n * @notice This contract is the remote representation for some token that lives on another network,\\n * typically an Optimism representation of an Ethereum-based token. Standard reference\\n * implementation that can be extended or modified according to your needs.\\n */\\ncontract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n uint256 public immutable remoteChainId;\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n address public immutable remoteToken;\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n address public immutable bridge;\\n\\n /**\\n * @notice Base token URI for this token.\\n */\\n string public baseTokenURI;\\n\\n /**\\n * @param _bridge Address of the bridge on this network.\\n * @param _remoteChainId Chain ID where the remote token is deployed.\\n * @param _remoteToken Address of the corresponding token on the other network.\\n * @param _name ERC721 name.\\n * @param _symbol ERC721 symbol.\\n */\\n constructor(\\n address _bridge,\\n uint256 _remoteChainId,\\n address _remoteToken,\\n string memory _name,\\n string memory _symbol\\n ) ERC721(_name, _symbol) {\\n remoteChainId = _remoteChainId;\\n remoteToken = _remoteToken;\\n bridge = _bridge;\\n\\n // Creates a base URI in the format specified by EIP-681:\\n // https://eips.ethereum.org/EIPS/eip-681\\n baseTokenURI = string(\\n abi.encodePacked(\\n \\\"ethereum:\\\",\\n Strings.toHexString(uint160(_remoteToken), 20),\\n \\\"@\\\",\\n Strings.toString(_remoteChainId),\\n \\\"/tokenURI?uint256=\\\"\\n )\\n );\\n }\\n\\n /**\\n * @notice Modifier that prevents callers other than the bridge from calling the function.\\n */\\n modifier onlyBridge() {\\n require(msg.sender == bridge, \\\"OptimismMintableERC721: only bridge can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n function mint(address _to, uint256 _tokenId) external virtual onlyBridge {\\n _mint(_to, _tokenId);\\n\\n emit Mint(_to, _tokenId);\\n }\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n function burn(address _from, uint256 _tokenId) external virtual onlyBridge {\\n _burn(_tokenId);\\n\\n emit Burn(_from, _tokenId);\\n }\\n\\n /**\\n * @notice Checks if a given interface ID is supported by this contract.\\n *\\n * @param _interfaceId The interface ID to check.\\n *\\n * @return True if the interface ID is supported, false otherwise.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n override(ERC721Enumerable, IERC165)\\n returns (bool)\\n {\\n bytes4 iface1 = type(IERC165).interfaceId;\\n bytes4 iface2 = type(IOptimismMintableERC721).interfaceId;\\n return\\n _interfaceId == iface1 ||\\n _interfaceId == iface2 ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n /**\\n * @notice Returns the base token URI.\\n *\\n * @return Base token URI.\\n */\\n function _baseURI() internal view virtual override returns (string memory) {\\n return baseTokenURI;\\n }\\n}\\n\",\"keccak256\":\"0x17e95ad4b50feae5284f91e17d6ac2245118879aa3964e7bc29e7d8a7d9b0056\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/OptimismMintableERC721Factory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport { OptimismMintableERC721 } from \\\"./OptimismMintableERC721.sol\\\";\\nimport { Semver } from \\\"../Semver.sol\\\";\\n\\n/**\\n * @title OptimismMintableERC721Factory\\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\\n */\\ncontract OptimismMintableERC721Factory is Semver, OwnableUpgradeable {\\n /**\\n * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\\n *\\n * @param remoteToken Address of the token on the remote domain.\\n * @param localToken Address of the token on the this domain.\\n */\\n event OptimismMintableERC721Created(address indexed remoteToken, address indexed localToken);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n address public bridge;\\n\\n /**\\n * @notice Chain ID for the remote network.\\n */\\n uint256 public remoteChainId;\\n\\n /**\\n * @notice Tracks addresses created by this factory.\\n */\\n mapping(address => bool) public isStandardOptimismMintableERC721;\\n\\n /**\\n * @param _bridge Address of the ERC721 bridge on this network.\\n */\\n constructor(address _bridge, uint256 _remoteChainId) Semver(0, 0, 1) {\\n initialize(_bridge, _remoteChainId);\\n }\\n\\n /**\\n * @notice Initializes the factory.\\n *\\n * @param _bridge Address of the ERC721 bridge on this network.\\n */\\n function initialize(address _bridge, uint256 _remoteChainId) public initializer {\\n bridge = _bridge;\\n remoteChainId = _remoteChainId;\\n\\n // Initialize upgradable OZ contracts\\n __Ownable_init();\\n }\\n\\n /**\\n * @notice Creates an instance of the standard ERC721.\\n *\\n * @param _remoteToken Address of the corresponding token on the other domain.\\n * @param _name ERC721 name.\\n * @param _symbol ERC721 symbol.\\n */\\n function createStandardOptimismMintableERC721(\\n address _remoteToken,\\n string memory _name,\\n string memory _symbol\\n ) external {\\n require(\\n _remoteToken != address(0),\\n \\\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\\\"\\n );\\n\\n require(\\n bridge != address(0),\\n \\\"OptimismMintableERC721Factory: bridge address must be initialized\\\"\\n );\\n\\n OptimismMintableERC721 localToken = new OptimismMintableERC721(\\n bridge,\\n remoteChainId,\\n _remoteToken,\\n _name,\\n _symbol\\n );\\n\\n isStandardOptimismMintableERC721[address(localToken)] = true;\\n emit OptimismMintableERC721Created(_remoteToken, address(localToken));\\n }\\n}\\n\",\"keccak256\":\"0xd9fd1f8589ee81de0b06de16d2a805206bf399e68edf922ceef3a772e4159aff\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b5060405162003d5c38038062003d5c833981016040819052620000349162000330565b6000608081905260a052600160c0526200004f828262000057565b50506200036c565b6000620000656001620000f4565b905080156200007e576000805461ff0019166101001790555b606580546001600160a01b0319166001600160a01b0385161790556066829055620000a862000206565b8015620000ef576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60008054610100900460ff16156200018d578160ff1660011480156200012d57506200012b306200026e60201b620007a31760201c565b155b620001855760405162461bcd60e51b815260206004820152602e602482015260008051602062003d1c83398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b506000919050565b60005460ff808416911610620001ec5760405162461bcd60e51b815260206004820152602e602482015260008051602062003d1c83398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016200017c565b506000805460ff191660ff92909216919091179055600190565b600054610100900460ff16620002625760405162461bcd60e51b815260206004820152602b602482015260008051602062003d3c83398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200017c565b6200026c6200027d565b565b6001600160a01b03163b151590565b600054610100900460ff16620002d95760405162461bcd60e51b815260206004820152602b602482015260008051602062003d3c83398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200017c565b6200026c33603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080604083850312156200034457600080fd5b82516001600160a01b03811681146200035c57600080fd5b6020939093015192949293505050565b60805160a05160c0516139816200039b600039600060e4015260006101b90152600061023a01526139816000f3fe60806040523480156200001157600080fd5b5060043610620000d95760003560e01c8063c8b91531116200008b578063e95181961162000062578063e95181961462000213578063f2fde38b146200021d578063f786becd146200023457600080fd5b8063c8b9153114620001b3578063cd6dc68714620001db578063e78cea9214620001f257600080fd5b80637aaa038e11620000c05780637aaa038e14620001255780638cf80c24146200013c5780638da5cb5b146200017357600080fd5b80636bf2606a14620000de578063715018a61462000119575b600080fd5b620001067f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b620001236200025c565b005b620001236200013636600462000c1d565b620002f1565b620001626200014d36600462000c9a565b60676020526000908152604090205460ff1681565b604051901515815260200162000110565b60335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000110565b620001067f000000000000000000000000000000000000000000000000000000000000000081565b62000123620001ec36600462000cbf565b62000571565b6065546200018d9073ffffffffffffffffffffffffffffffffffffffff1681565b6200010660665481565b620001236200022e36600462000c9a565b6200066d565b620001067f000000000000000000000000000000000000000000000000000000000000000081565b60335473ffffffffffffffffffffffffffffffffffffffff163314620002e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b620002ef6000620007bf565b565b73ffffffffffffffffffffffffffffffffffffffff8316620003bd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a204c908201527f3120746f6b656e20616464726573732063616e6e6f742062652061646472657360648201527f7328302900000000000000000000000000000000000000000000000000000000608482015260a401620002da565b60655473ffffffffffffffffffffffffffffffffffffffff166200048a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a206260448201527f72696467652061646472657373206d75737420626520696e697469616c697a6560648201527f6400000000000000000000000000000000000000000000000000000000000000608482015260a401620002da565b60655460665460405160009273ffffffffffffffffffffffffffffffffffffffff169190869086908690620004bf9062000b08565b620004cf95949392919062000d5a565b604051809103906000f080158015620004ec573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff80821660008181526067602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055519394509092918716917fe6575823a81be7bedfd159bbb82da5f9efee2a8bdfcd2c50f959d6b0670ea6a89190a350505050565b60006200057f600162000836565b90508015620005b557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8516179055606682905562000604620009c7565b80156200066857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314620006f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620002da565b73ffffffffffffffffffffffffffffffffffffffff811662000795576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401620002da565b620007a081620007bf565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008054610100900460ff1615620008f1578160ff1660011480156200085b5750303b155b620008e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620002da565b506000919050565b60005460ff8084169116106200098a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620002da565b50600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055600190565b919050565b600054610100900460ff1662000a60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620002da565b620002ef600054610100900460ff1662000afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620002da565b620002ef33620007bf565b612b908062000dbc83390190565b803573ffffffffffffffffffffffffffffffffffffffff81168114620009c257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011262000b7c57600080fd5b813567ffffffffffffffff8082111562000b9a5762000b9a62000b3b565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171562000be35762000be362000b3b565b8160405283815286602085880101111562000bfd57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121562000c3357600080fd5b62000c3e8462000b16565b9250602084013567ffffffffffffffff8082111562000c5c57600080fd5b62000c6a8783880162000b6a565b9350604086013591508082111562000c8157600080fd5b5062000c908682870162000b6a565b9150509250925092565b60006020828403121562000cad57600080fd5b62000cb88262000b16565b9392505050565b6000806040838503121562000cd357600080fd5b62000cde8362000b16565b946020939093013593505050565b6000815180845260005b8181101562000d145760208185018101518683018201520162000cf6565b8181111562000d27576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808816835286602084015280861660408401525060a0606083015262000d9b60a083018562000cec565b828103608084015262000daf818562000cec565b9897505050505050505056fe60e06040523480156200001157600080fd5b5060405162002b9038038062002b90833981016040819052620000349162000572565b8151829082906200004d906000906020850190620003d5565b50805162000063906001906020840190620003d5565b50505060808490526001600160a01b0383811660a081905290861660c0526200009a906014620000f5602090811b62000dd317901c565b620000b085620002b860201b62000ffc1760201c565b604051602001620000c39291906200060c565b604051602081830303815290604052600a9080519060200190620000e9929190620003d5565b505050505050620007bc565b606060006200010683600262000696565b62000113906002620006b8565b6001600160401b038111156200012d576200012d62000498565b6040519080825280601f01601f19166020018201604052801562000158576020820181803683370190505b509050600360fc1b81600081518110620001765762000176620006d3565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110620001a857620001a8620006d3565b60200101906001600160f81b031916908160001a9053506000620001ce84600262000696565b620001db906001620006b8565b90505b60018111156200025d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620002135762000213620006d3565b1a60f81b8282815181106200022c576200022c620006d3565b60200101906001600160f81b031916908160001a90535060049490941c936200025581620006e9565b9050620001de565b508315620002b15760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640160405180910390fd5b9392505050565b606081620002dd5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156200030d5780620002f48162000703565b9150620003059050600a8362000737565b9150620002e1565b6000816001600160401b038111156200032a576200032a62000498565b6040519080825280601f01601f19166020018201604052801562000355576020820181803683370190505b5090505b8415620003cd576200036d6001836200074e565b91506200037c600a8662000768565b62000389906030620006b8565b60f81b818381518110620003a157620003a1620006d3565b60200101906001600160f81b031916908160001a905350620003c5600a8662000737565b945062000359565b949350505050565b828054620003e3906200077f565b90600052602060002090601f01602090048101928262000407576000855562000452565b82601f106200042257805160ff191683800117855562000452565b8280016001018555821562000452579182015b828111156200045257825182559160200191906001019062000435565b506200046092915062000464565b5090565b5b8082111562000460576000815560010162000465565b80516001600160a01b03811681146200049357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620004cb578181015183820152602001620004b1565b83811115620004db576000848401525b50505050565b600082601f830112620004f357600080fd5b81516001600160401b038082111562000510576200051062000498565b604051601f8301601f19908116603f011681019082821181831017156200053b576200053b62000498565b816040528381528660208588010111156200055557600080fd5b62000568846020830160208901620004ae565b9695505050505050565b600080600080600060a086880312156200058b57600080fd5b62000596866200047b565b945060208601519350620005ad604087016200047b565b60608701519093506001600160401b0380821115620005cb57600080fd5b620005d989838a01620004e1565b93506080880151915080821115620005f057600080fd5b50620005ff88828901620004e1565b9150509295509295909350565b6832ba3432b932bab69d60b91b81526000835162000632816009850160208801620004ae565b600160fe1b60099184019182015283516200065581600a840160208801620004ae565b712f746f6b656e5552493f75696e743235363d60701b600a9290910191820152601c01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620006b357620006b362000680565b500290565b60008219821115620006ce57620006ce62000680565b500190565b634e487b7160e01b600052603260045260246000fd5b600081620006fb57620006fb62000680565b506000190190565b60006000198214156200071a576200071a62000680565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008262000749576200074962000721565b500490565b60008282101562000763576200076362000680565b500390565b6000826200077a576200077a62000721565b500690565b600181811c908216806200079457607f821691505b60208210811415620007b657634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c051612396620007fa60003960008181610323015281816108000152610ae8015260006102fc0152600061034a01526123966000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c806370a08231116100d8578063c87b56dd1161008c578063e78cea9211610066578063e78cea921461031e578063e951819614610345578063e985e9c51461036c57600080fd5b8063c87b56dd146102dc578063d547cfb7146102ef578063d6c0b2c4146102f757600080fd5b80639dc29fac116100bd5780639dc29fac146102a3578063a22cb465146102b6578063b88d4fde146102c957600080fd5b806370a082311461028857806395d89b411461029b57600080fd5b806323b872dd1161013a57806342842e0e1161011457806342842e0e1461024f5780634f6ccce7146102625780636352211e1461027557600080fd5b806323b872dd146102165780632f745c591461022957806340c10f191461023c57600080fd5b8063081812fc1161016b578063081812fc146101c4578063095ea7b3146101ef57806318160ddd1461020457600080fd5b806301ffc9a71461018757806306fdde03146101af575b600080fd5b61019a610195366004611dd2565b6103a8565b60405190151581526020015b60405180910390f35b6101b7610457565b6040516101a69190611e65565b6101d76101d2366004611e78565b6104e9565b6040516001600160a01b0390911681526020016101a6565b6102026101fd366004611ead565b610594565b005b6008545b6040519081526020016101a6565b610202610224366004611ed7565b6106c6565b610208610237366004611ead565b61074d565b61020261024a366004611ead565b6107f5565b61020261025d366004611ed7565b6108e4565b610208610270366004611e78565b6108ff565b6101d7610283366004611e78565b6109a3565b610208610296366004611f13565b610a34565b6101b7610ace565b6102026102b1366004611ead565b610add565b6102026102c4366004611f2e565b610bbf565b6102026102d7366004611f99565b610bce565b6101b76102ea366004611e78565b610c5c565b6101b7610d45565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6102087f000000000000000000000000000000000000000000000000000000000000000081565b61019a61037a366004612093565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f051e4975000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841682148061044057507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b8061044f575061044f8461112e565b949350505050565b606060008054610466906120c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610492906120c6565b80156104df5780601f106104b4576101008083540402835291602001916104df565b820191906000526020600020905b8154815290600101906020018083116104c257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166105785760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061059f826109a3565b9050806001600160a01b0316836001600160a01b031614156106295760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161056f565b336001600160a01b03821614806106455750610645813361037a565b6106b75760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161056f565b6106c18383611184565b505050565b6106d0338261120a565b6107425760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b6106c1838383611311565b600061075883610a34565b82106107cc5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e6473000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108935760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b61089d8282611501565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516108d891815260200190565b60405180910390a25050565b6106c183838360405180602001604052806000815250610bce565b600061090a60085490565b821061097e5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e64730000000000000000000000000000000000000000606482015260840161056f565b600882815481106109915761099161211a565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b031680610a2e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e0000000000000000000000000000000000000000000000606482015260840161056f565b92915050565b60006001600160a01b038216610ab25760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f206164647265737300000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b031660009081526003602052604090205490565b606060018054610466906120c6565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b7b5760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610b8481611667565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516108d891815260200190565b610bca338383611726565b5050565b610bd8338361120a565b610c4a5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b610c5684848484611813565b50505050565b6000818152600260205260409020546060906001600160a01b0316610ce95760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000606482015260840161056f565b6000610cf361189c565b90506000815111610d135760405180602001604052806000815250610d3e565b80610d1d84610ffc565b604051602001610d2e929190612149565b6040516020818303038152906040525b9392505050565b600a8054610d52906120c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7e906120c6565b8015610dcb5780601f10610da057610100808354040283529160200191610dcb565b820191906000526020600020905b815481529060010190602001808311610dae57829003601f168201915b505050505081565b60606000610de28360026121a7565b610ded9060026121e4565b67ffffffffffffffff811115610e0557610e05611f6a565b6040519080825280601f01601f191660200182016040528015610e2f576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110610e6657610e6661211a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110610ec957610ec961211a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000610f058460026121a7565b610f109060016121e4565b90505b6001811115610fad577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110610f5157610f5161211a565b1a60f81b828281518110610f6757610f6761211a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93610fa6816121fc565b9050610f13565b508315610d3e5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161056f565b60608161103c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611066578061105081612231565b915061105f9050600a83612299565b9150611040565b60008167ffffffffffffffff81111561108157611081611f6a565b6040519080825280601f01601f1916602001820160405280156110ab576020820181803683370190505b5090505b841561044f576110c06001836122ad565b91506110cd600a866122c4565b6110d89060306121e4565b60f81b8183815181106110ed576110ed61211a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611127600a86612299565b94506110af565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610a2e5750610a2e826118ab565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841690811790915581906111d1826109a3565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166112945760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606482015260840161056f565b600061129f836109a3565b9050806001600160a01b0316846001600160a01b031614806112e657506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b8061044f5750836001600160a01b03166112ff846104e9565b6001600160a01b031614949350505050565b826001600160a01b0316611324826109a3565b6001600160a01b0316146113a05760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e6572000000000000000000000000000000000000000000000000000000606482015260840161056f565b6001600160a01b03821661141b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161056f565b61142683838361198e565b611431600082611184565b6001600160a01b038316600090815260036020526040812080546001929061145a9084906122ad565b90915550506001600160a01b03821660009081526003602052604081208054600192906114889084906121e4565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6001600160a01b0382166115575760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161056f565b6000818152600260205260409020546001600160a01b0316156115bc5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056f565b6115c86000838361198e565b6001600160a01b03821660009081526003602052604081208054600192906115f19084906121e4565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000611672826109a3565b90506116808160008461198e565b61168b600083611184565b6001600160a01b03811660009081526003602052604081208054600192906116b49084906122ad565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b816001600160a01b0316836001600160a01b031614156117885760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161056f565b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b61181e848484611311565b61182a84848484611a46565b610c565760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b6060600a8054610466906120c6565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061193e57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610a2e57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610a2e565b6001600160a01b0383166119e9576119e481600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611a0c565b816001600160a01b0316836001600160a01b031614611a0c57611a0c8382611c11565b6001600160a01b038216611a23576106c181611cae565b826001600160a01b0316826001600160a01b0316146106c1576106c18282611d5d565b60006001600160a01b0384163b15611c06576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290611aa39033908990889088906004016122d8565b602060405180830381600087803b158015611abd57600080fd5b505af1925050508015611b0b575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611b0891810190612314565b60015b611bbb573d808015611b39576040519150601f19603f3d011682016040523d82523d6000602084013e611b3e565b606091505b508051611bb35760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a020000000000000000000000000000000000000000000000000000000014905061044f565b506001949350505050565b60006001611c1e84610a34565b611c2891906122ad565b600083815260076020526040902054909150808214611c7b576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611cc0906001906122ad565b60008381526009602052604081205460088054939450909284908110611ce857611ce861211a565b906000526020600020015490508060088381548110611d0957611d0961211a565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611d4157611d41612331565b6001900381819060005260206000200160009055905550505050565b6000611d6883610a34565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611dcf57600080fd5b50565b600060208284031215611de457600080fd5b8135610d3e81611da1565b60005b83811015611e0a578181015183820152602001611df2565b83811115610c565750506000910152565b60008151808452611e33816020860160208601611def565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d3e6020830184611e1b565b600060208284031215611e8a57600080fd5b5035919050565b80356001600160a01b0381168114611ea857600080fd5b919050565b60008060408385031215611ec057600080fd5b611ec983611e91565b946020939093013593505050565b600080600060608486031215611eec57600080fd5b611ef584611e91565b9250611f0360208501611e91565b9150604084013590509250925092565b600060208284031215611f2557600080fd5b610d3e82611e91565b60008060408385031215611f4157600080fd5b611f4a83611e91565b915060208301358015158114611f5f57600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060008060808587031215611faf57600080fd5b611fb885611e91565b9350611fc660208601611e91565b925060408501359150606085013567ffffffffffffffff80821115611fea57600080fd5b818701915087601f830112611ffe57600080fd5b81358181111561201057612010611f6a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561205657612056611f6a565b816040528281528a602084870101111561206f57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600080604083850312156120a657600080fd5b6120af83611e91565b91506120bd60208401611e91565b90509250929050565b600181811c908216806120da57607f821691505b60208210811415612114577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000835161215b818460208801611def565b83519083019061216f818360208801611def565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156121df576121df612178565b500290565b600082198211156121f7576121f7612178565b500190565b60008161220b5761220b612178565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561226357612263612178565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826122a8576122a861226a565b500490565b6000828210156122bf576122bf612178565b500390565b6000826122d3576122d361226a565b500690565b60006001600160a01b0380871683528086166020840152508360408301526080606083015261230a6080830184611e1b565b9695505050505050565b60006020828403121561232657600080fd5b8151610d3e81611da1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea264697066735822122093ab190002b667e548bc69785456c0a905487c4342aafdd77ba602f8ff933a5e64736f6c63430008090033a26469706673582212203ad8746e0f0dd169ca60cfc8f0ada92eaba0bced97450dc08b1ef0920fa05c2264736f6c63430008090033496e697469616c697a61626c653a20636f6e747261637420697320616c726561496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620000d95760003560e01c8063c8b91531116200008b578063e95181961162000062578063e95181961462000213578063f2fde38b146200021d578063f786becd146200023457600080fd5b8063c8b9153114620001b3578063cd6dc68714620001db578063e78cea9214620001f257600080fd5b80637aaa038e11620000c05780637aaa038e14620001255780638cf80c24146200013c5780638da5cb5b146200017357600080fd5b80636bf2606a14620000de578063715018a61462000119575b600080fd5b620001067f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b620001236200025c565b005b620001236200013636600462000c1d565b620002f1565b620001626200014d36600462000c9a565b60676020526000908152604090205460ff1681565b604051901515815260200162000110565b60335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000110565b620001067f000000000000000000000000000000000000000000000000000000000000000081565b62000123620001ec36600462000cbf565b62000571565b6065546200018d9073ffffffffffffffffffffffffffffffffffffffff1681565b6200010660665481565b620001236200022e36600462000c9a565b6200066d565b620001067f000000000000000000000000000000000000000000000000000000000000000081565b60335473ffffffffffffffffffffffffffffffffffffffff163314620002e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b620002ef6000620007bf565b565b73ffffffffffffffffffffffffffffffffffffffff8316620003bd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a204c908201527f3120746f6b656e20616464726573732063616e6e6f742062652061646472657360648201527f7328302900000000000000000000000000000000000000000000000000000000608482015260a401620002da565b60655473ffffffffffffffffffffffffffffffffffffffff166200048a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a206260448201527f72696467652061646472657373206d75737420626520696e697469616c697a6560648201527f6400000000000000000000000000000000000000000000000000000000000000608482015260a401620002da565b60655460665460405160009273ffffffffffffffffffffffffffffffffffffffff169190869086908690620004bf9062000b08565b620004cf95949392919062000d5a565b604051809103906000f080158015620004ec573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff80821660008181526067602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055519394509092918716917fe6575823a81be7bedfd159bbb82da5f9efee2a8bdfcd2c50f959d6b0670ea6a89190a350505050565b60006200057f600162000836565b90508015620005b557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8516179055606682905562000604620009c7565b80156200066857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314620006f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620002da565b73ffffffffffffffffffffffffffffffffffffffff811662000795576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401620002da565b620007a081620007bf565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008054610100900460ff1615620008f1578160ff1660011480156200085b5750303b155b620008e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620002da565b506000919050565b60005460ff8084169116106200098a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620002da565b50600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055600190565b919050565b600054610100900460ff1662000a60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620002da565b620002ef600054610100900460ff1662000afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620002da565b620002ef33620007bf565b612b908062000dbc83390190565b803573ffffffffffffffffffffffffffffffffffffffff81168114620009c257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011262000b7c57600080fd5b813567ffffffffffffffff8082111562000b9a5762000b9a62000b3b565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171562000be35762000be362000b3b565b8160405283815286602085880101111562000bfd57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121562000c3357600080fd5b62000c3e8462000b16565b9250602084013567ffffffffffffffff8082111562000c5c57600080fd5b62000c6a8783880162000b6a565b9350604086013591508082111562000c8157600080fd5b5062000c908682870162000b6a565b9150509250925092565b60006020828403121562000cad57600080fd5b62000cb88262000b16565b9392505050565b6000806040838503121562000cd357600080fd5b62000cde8362000b16565b946020939093013593505050565b6000815180845260005b8181101562000d145760208185018101518683018201520162000cf6565b8181111562000d27576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808816835286602084015280861660408401525060a0606083015262000d9b60a083018562000cec565b828103608084015262000daf818562000cec565b9897505050505050505056fe60e06040523480156200001157600080fd5b5060405162002b9038038062002b90833981016040819052620000349162000572565b8151829082906200004d906000906020850190620003d5565b50805162000063906001906020840190620003d5565b50505060808490526001600160a01b0383811660a081905290861660c0526200009a906014620000f5602090811b62000dd317901c565b620000b085620002b860201b62000ffc1760201c565b604051602001620000c39291906200060c565b604051602081830303815290604052600a9080519060200190620000e9929190620003d5565b505050505050620007bc565b606060006200010683600262000696565b62000113906002620006b8565b6001600160401b038111156200012d576200012d62000498565b6040519080825280601f01601f19166020018201604052801562000158576020820181803683370190505b509050600360fc1b81600081518110620001765762000176620006d3565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110620001a857620001a8620006d3565b60200101906001600160f81b031916908160001a9053506000620001ce84600262000696565b620001db906001620006b8565b90505b60018111156200025d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620002135762000213620006d3565b1a60f81b8282815181106200022c576200022c620006d3565b60200101906001600160f81b031916908160001a90535060049490941c936200025581620006e9565b9050620001de565b508315620002b15760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640160405180910390fd5b9392505050565b606081620002dd5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156200030d5780620002f48162000703565b9150620003059050600a8362000737565b9150620002e1565b6000816001600160401b038111156200032a576200032a62000498565b6040519080825280601f01601f19166020018201604052801562000355576020820181803683370190505b5090505b8415620003cd576200036d6001836200074e565b91506200037c600a8662000768565b62000389906030620006b8565b60f81b818381518110620003a157620003a1620006d3565b60200101906001600160f81b031916908160001a905350620003c5600a8662000737565b945062000359565b949350505050565b828054620003e3906200077f565b90600052602060002090601f01602090048101928262000407576000855562000452565b82601f106200042257805160ff191683800117855562000452565b8280016001018555821562000452579182015b828111156200045257825182559160200191906001019062000435565b506200046092915062000464565b5090565b5b8082111562000460576000815560010162000465565b80516001600160a01b03811681146200049357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620004cb578181015183820152602001620004b1565b83811115620004db576000848401525b50505050565b600082601f830112620004f357600080fd5b81516001600160401b038082111562000510576200051062000498565b604051601f8301601f19908116603f011681019082821181831017156200053b576200053b62000498565b816040528381528660208588010111156200055557600080fd5b62000568846020830160208901620004ae565b9695505050505050565b600080600080600060a086880312156200058b57600080fd5b62000596866200047b565b945060208601519350620005ad604087016200047b565b60608701519093506001600160401b0380821115620005cb57600080fd5b620005d989838a01620004e1565b93506080880151915080821115620005f057600080fd5b50620005ff88828901620004e1565b9150509295509295909350565b6832ba3432b932bab69d60b91b81526000835162000632816009850160208801620004ae565b600160fe1b60099184019182015283516200065581600a840160208801620004ae565b712f746f6b656e5552493f75696e743235363d60701b600a9290910191820152601c01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620006b357620006b362000680565b500290565b60008219821115620006ce57620006ce62000680565b500190565b634e487b7160e01b600052603260045260246000fd5b600081620006fb57620006fb62000680565b506000190190565b60006000198214156200071a576200071a62000680565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008262000749576200074962000721565b500490565b60008282101562000763576200076362000680565b500390565b6000826200077a576200077a62000721565b500690565b600181811c908216806200079457607f821691505b60208210811415620007b657634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c051612396620007fa60003960008181610323015281816108000152610ae8015260006102fc0152600061034a01526123966000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c806370a08231116100d8578063c87b56dd1161008c578063e78cea9211610066578063e78cea921461031e578063e951819614610345578063e985e9c51461036c57600080fd5b8063c87b56dd146102dc578063d547cfb7146102ef578063d6c0b2c4146102f757600080fd5b80639dc29fac116100bd5780639dc29fac146102a3578063a22cb465146102b6578063b88d4fde146102c957600080fd5b806370a082311461028857806395d89b411461029b57600080fd5b806323b872dd1161013a57806342842e0e1161011457806342842e0e1461024f5780634f6ccce7146102625780636352211e1461027557600080fd5b806323b872dd146102165780632f745c591461022957806340c10f191461023c57600080fd5b8063081812fc1161016b578063081812fc146101c4578063095ea7b3146101ef57806318160ddd1461020457600080fd5b806301ffc9a71461018757806306fdde03146101af575b600080fd5b61019a610195366004611dd2565b6103a8565b60405190151581526020015b60405180910390f35b6101b7610457565b6040516101a69190611e65565b6101d76101d2366004611e78565b6104e9565b6040516001600160a01b0390911681526020016101a6565b6102026101fd366004611ead565b610594565b005b6008545b6040519081526020016101a6565b610202610224366004611ed7565b6106c6565b610208610237366004611ead565b61074d565b61020261024a366004611ead565b6107f5565b61020261025d366004611ed7565b6108e4565b610208610270366004611e78565b6108ff565b6101d7610283366004611e78565b6109a3565b610208610296366004611f13565b610a34565b6101b7610ace565b6102026102b1366004611ead565b610add565b6102026102c4366004611f2e565b610bbf565b6102026102d7366004611f99565b610bce565b6101b76102ea366004611e78565b610c5c565b6101b7610d45565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6102087f000000000000000000000000000000000000000000000000000000000000000081565b61019a61037a366004612093565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f051e4975000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841682148061044057507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b8061044f575061044f8461112e565b949350505050565b606060008054610466906120c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610492906120c6565b80156104df5780601f106104b4576101008083540402835291602001916104df565b820191906000526020600020905b8154815290600101906020018083116104c257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166105785760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061059f826109a3565b9050806001600160a01b0316836001600160a01b031614156106295760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161056f565b336001600160a01b03821614806106455750610645813361037a565b6106b75760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161056f565b6106c18383611184565b505050565b6106d0338261120a565b6107425760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b6106c1838383611311565b600061075883610a34565b82106107cc5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e6473000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108935760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b61089d8282611501565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516108d891815260200190565b60405180910390a25050565b6106c183838360405180602001604052806000815250610bce565b600061090a60085490565b821061097e5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e64730000000000000000000000000000000000000000606482015260840161056f565b600882815481106109915761099161211a565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b031680610a2e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e0000000000000000000000000000000000000000000000606482015260840161056f565b92915050565b60006001600160a01b038216610ab25760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f206164647265737300000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b031660009081526003602052604090205490565b606060018054610466906120c6565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b7b5760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610b8481611667565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516108d891815260200190565b610bca338383611726565b5050565b610bd8338361120a565b610c4a5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b610c5684848484611813565b50505050565b6000818152600260205260409020546060906001600160a01b0316610ce95760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000606482015260840161056f565b6000610cf361189c565b90506000815111610d135760405180602001604052806000815250610d3e565b80610d1d84610ffc565b604051602001610d2e929190612149565b6040516020818303038152906040525b9392505050565b600a8054610d52906120c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7e906120c6565b8015610dcb5780601f10610da057610100808354040283529160200191610dcb565b820191906000526020600020905b815481529060010190602001808311610dae57829003601f168201915b505050505081565b60606000610de28360026121a7565b610ded9060026121e4565b67ffffffffffffffff811115610e0557610e05611f6a565b6040519080825280601f01601f191660200182016040528015610e2f576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110610e6657610e6661211a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110610ec957610ec961211a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000610f058460026121a7565b610f109060016121e4565b90505b6001811115610fad577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110610f5157610f5161211a565b1a60f81b828281518110610f6757610f6761211a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93610fa6816121fc565b9050610f13565b508315610d3e5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161056f565b60608161103c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611066578061105081612231565b915061105f9050600a83612299565b9150611040565b60008167ffffffffffffffff81111561108157611081611f6a565b6040519080825280601f01601f1916602001820160405280156110ab576020820181803683370190505b5090505b841561044f576110c06001836122ad565b91506110cd600a866122c4565b6110d89060306121e4565b60f81b8183815181106110ed576110ed61211a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611127600a86612299565b94506110af565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610a2e5750610a2e826118ab565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841690811790915581906111d1826109a3565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166112945760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606482015260840161056f565b600061129f836109a3565b9050806001600160a01b0316846001600160a01b031614806112e657506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b8061044f5750836001600160a01b03166112ff846104e9565b6001600160a01b031614949350505050565b826001600160a01b0316611324826109a3565b6001600160a01b0316146113a05760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e6572000000000000000000000000000000000000000000000000000000606482015260840161056f565b6001600160a01b03821661141b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161056f565b61142683838361198e565b611431600082611184565b6001600160a01b038316600090815260036020526040812080546001929061145a9084906122ad565b90915550506001600160a01b03821660009081526003602052604081208054600192906114889084906121e4565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6001600160a01b0382166115575760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161056f565b6000818152600260205260409020546001600160a01b0316156115bc5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056f565b6115c86000838361198e565b6001600160a01b03821660009081526003602052604081208054600192906115f19084906121e4565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000611672826109a3565b90506116808160008461198e565b61168b600083611184565b6001600160a01b03811660009081526003602052604081208054600192906116b49084906122ad565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b816001600160a01b0316836001600160a01b031614156117885760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161056f565b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b61181e848484611311565b61182a84848484611a46565b610c565760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b6060600a8054610466906120c6565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061193e57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610a2e57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610a2e565b6001600160a01b0383166119e9576119e481600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611a0c565b816001600160a01b0316836001600160a01b031614611a0c57611a0c8382611c11565b6001600160a01b038216611a23576106c181611cae565b826001600160a01b0316826001600160a01b0316146106c1576106c18282611d5d565b60006001600160a01b0384163b15611c06576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290611aa39033908990889088906004016122d8565b602060405180830381600087803b158015611abd57600080fd5b505af1925050508015611b0b575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611b0891810190612314565b60015b611bbb573d808015611b39576040519150601f19603f3d011682016040523d82523d6000602084013e611b3e565b606091505b508051611bb35760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a020000000000000000000000000000000000000000000000000000000014905061044f565b506001949350505050565b60006001611c1e84610a34565b611c2891906122ad565b600083815260076020526040902054909150808214611c7b576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611cc0906001906122ad565b60008381526009602052604081205460088054939450909284908110611ce857611ce861211a565b906000526020600020015490508060088381548110611d0957611d0961211a565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611d4157611d41612331565b6001900381819060005260206000200160009055905550505050565b6000611d6883610a34565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611dcf57600080fd5b50565b600060208284031215611de457600080fd5b8135610d3e81611da1565b60005b83811015611e0a578181015183820152602001611df2565b83811115610c565750506000910152565b60008151808452611e33816020860160208601611def565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d3e6020830184611e1b565b600060208284031215611e8a57600080fd5b5035919050565b80356001600160a01b0381168114611ea857600080fd5b919050565b60008060408385031215611ec057600080fd5b611ec983611e91565b946020939093013593505050565b600080600060608486031215611eec57600080fd5b611ef584611e91565b9250611f0360208501611e91565b9150604084013590509250925092565b600060208284031215611f2557600080fd5b610d3e82611e91565b60008060408385031215611f4157600080fd5b611f4a83611e91565b915060208301358015158114611f5f57600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060008060808587031215611faf57600080fd5b611fb885611e91565b9350611fc660208601611e91565b925060408501359150606085013567ffffffffffffffff80821115611fea57600080fd5b818701915087601f830112611ffe57600080fd5b81358181111561201057612010611f6a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561205657612056611f6a565b816040528281528a602084870101111561206f57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600080604083850312156120a657600080fd5b6120af83611e91565b91506120bd60208401611e91565b90509250929050565b600181811c908216806120da57607f821691505b60208210811415612114577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000835161215b818460208801611def565b83519083019061216f818360208801611def565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156121df576121df612178565b500290565b600082198211156121f7576121f7612178565b500190565b60008161220b5761220b612178565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561226357612263612178565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826122a8576122a861226a565b500490565b6000828210156122bf576122bf612178565b500390565b6000826122d3576122d361226a565b500690565b60006001600160a01b0380871683528086166020840152508360408301526080606083015261230a6080830184611e1b565b9695505050505050565b60006020828403121561232657600080fd5b8151610d3e81611da1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea264697066735822122093ab190002b667e548bc69785456c0a905487c4342aafdd77ba602f8ff933a5e64736f6c63430008090033a26469706673582212203ad8746e0f0dd169ca60cfc8f0ada92eaba0bced97450dc08b1ef0920fa05c2264736f6c63430008090033", - "devdoc": { - "events": { - "OptimismMintableERC721Created(address,address)": { - "params": { - "localToken": "Address of the token on the this domain.", - "remoteToken": "Address of the token on the remote domain." - } - } - }, - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_bridge": "Address of the ERC721 bridge on this network." - } - }, - "createStandardOptimismMintableERC721(address,string,string)": { - "params": { - "_name": "ERC721 name.", - "_remoteToken": "Address of the corresponding token on the other domain.", - "_symbol": "ERC721 symbol." - } - }, - "initialize(address,uint256)": { - "params": { - "_bridge": "Address of the ERC721 bridge on this network." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "title": "OptimismMintableERC721Factory", - "version": 1 - }, - "userdoc": { - "events": { - "OptimismMintableERC721Created(address,address)": { - "notice": "Emitted whenever a new OptimismMintableERC721 contract is created." - } - }, - "kind": "user", - "methods": { - "MAJOR_VERSION()": { - "notice": "Contract version number (major)." - }, - "MINOR_VERSION()": { - "notice": "Contract version number (minor)." - }, - "PATCH_VERSION()": { - "notice": "Contract version number (patch)." - }, - "bridge()": { - "notice": "Address of the ERC721 bridge on this network." - }, - "createStandardOptimismMintableERC721(address,string,string)": { - "notice": "Creates an instance of the standard ERC721." - }, - "initialize(address,uint256)": { - "notice": "Initializes the factory." - }, - "isStandardOptimismMintableERC721(address)": { - "notice": "Tracks addresses created by this factory." - }, - "remoteChainId()": { - "notice": "Chain ID for the remote network." - } - }, - "notice": "Factory contract for creating OptimismMintableERC721 contracts.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1361, - "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 1364, - "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 1780, - "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 1241, - "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 1353, - "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 7059, - "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", - "label": "bridge", - "offset": 0, - "slot": "101", - "type": "t_address" - }, - { - "astId": 7062, - "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", - "label": "remoteChainId", - "offset": 0, - "slot": "102", - "type": "t_uint256" - }, - { - "astId": 7067, - "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", - "label": "isStandardOptimismMintableERC721", - "offset": 0, - "slot": "103", - "type": "t_mapping(t_address,t_bool)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_bool)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-kovan/OptimismMintableERC721FactoryProxy.json b/packages/contracts-periphery/deployments/optimism-kovan/OptimismMintableERC721FactoryProxy.json deleted file mode 100644 index dde279bb2d6b1..0000000000000 --- a/packages/contracts-periphery/deployments/optimism-kovan/OptimismMintableERC721FactoryProxy.json +++ /dev/null @@ -1,224 +0,0 @@ -{ - "address": "0x10a561600Dd996DFFc540F3e860e1f20247Ce7f4", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_admin", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "admin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_admin", - "type": "address" - } - ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "implementation", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_implementation", - "type": "address" - } - ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_implementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } - ], - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "9bf33bb642648b258386a9c465b5d346", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"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\"}}},\"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 owner. The owner has the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"The address of the implementation contract\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"The calldata to delegatecall the new implementation with\",\"_implementation\":\"The address of the implementation contract\"}}},\"title\":\"Proxy\",\"version\":1},\"userdoc\":{\"events\":{\"AdminChanged(address,address)\":{\"notice\":\"An event that is emitted each time the owner is upgraded. This event is part of the EIP 1967 spec.\"},\"Upgraded(address)\":{\"notice\":\"An event that is emitted each time the implementation is changed. This event is part of the EIP 1967 spec.\"}},\"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\":\"set the initial owner during contract deployment. The owner is stored at the eip1967 owner storage slot so that storage collision with the implementation is not possible.\"},\"implementation()\":{\"notice\":\"Queries the implementation address.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at this address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. This is useful to ensure atomic `initialize()` based upgrades.\"}},\"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 offchain simulation.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Proxy\\n * @notice Proxy is a transparent proxy that passes through the call\\n * if the caller is the owner or if the caller is `address(0)`,\\n * meaning that the call originated from an offchain simulation.\\n */\\ncontract Proxy {\\n /**\\n * @notice An event that is emitted each time the implementation is changed.\\n * This event is part of the EIP 1967 spec.\\n *\\n * @param implementation The address of the implementation contract\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @notice An event that is emitted each time the owner is upgraded.\\n * This event is part of the EIP 1967 spec.\\n *\\n * @param previousAdmin The previous owner of the contract\\n * @param newAdmin The new owner of the contract\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @notice The storage slot that holds the address of the implementation.\\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n */\\n bytes32 internal constant IMPLEMENTATION_KEY =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @notice The storage slot that holds the address of the owner.\\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n */\\n bytes32 internal constant OWNER_KEY =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @notice set the initial owner during contract deployment. The\\n * owner is stored at the eip1967 owner storage slot so that\\n * storage collision with the implementation is not possible.\\n *\\n * @param _admin Address of the initial contract owner. The owner has\\n * the ability to access the transparent proxy interface.\\n */\\n constructor(address _admin) {\\n _changeAdmin(_admin);\\n }\\n\\n // slither-disable-next-line locked-ether\\n fallback() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n /**\\n * @notice A modifier that reverts if not called by the owner\\n * or by `address(0)` to allow `eth_call` to interact\\n * with the proxy without needing to use low level storage\\n * inspection. It is assumed that nobody controls the private\\n * key for `address(0)`.\\n */\\n modifier proxyCallIfNotAdmin() {\\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\\n _;\\n } else {\\n // This WILL halt the call frame on completion.\\n _doProxyCall();\\n }\\n }\\n\\n /**\\n * @notice Set the implementation contract address. The code at this\\n * address will execute when this contract is called.\\n *\\n * @param _implementation The address of the implementation contract\\n */\\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\\n _setImplementation(_implementation);\\n }\\n\\n /**\\n * @notice Set the implementation and call a function in a single\\n * transaction. This is useful to ensure atomic `initialize()`\\n * based upgrades.\\n *\\n * @param _implementation The address of the implementation contract\\n * @param _data The calldata to delegatecall the new\\n * implementation with\\n */\\n function upgradeToAndCall(address _implementation, bytes calldata _data)\\n external\\n payable\\n proxyCallIfNotAdmin\\n returns (bytes memory)\\n {\\n _setImplementation(_implementation);\\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\\n require(success);\\n return returndata;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\\n _changeAdmin(_admin);\\n }\\n\\n /**\\n * @notice Gets the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function admin() external proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() external proxyCallIfNotAdmin returns (address) {\\n return _getImplementation();\\n }\\n\\n /**\\n * @notice Sets the implementation address.\\n *\\n * @param _implementation New implementation address.\\n */\\n function _setImplementation(address _implementation) internal {\\n assembly {\\n sstore(IMPLEMENTATION_KEY, _implementation)\\n }\\n emit Upgraded(_implementation);\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n address implementation;\\n assembly {\\n implementation := sload(IMPLEMENTATION_KEY)\\n }\\n return implementation;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function _changeAdmin(address _admin) internal {\\n address previous = _getAdmin();\\n assembly {\\n sstore(OWNER_KEY, _admin)\\n }\\n emit AdminChanged(previous, _admin);\\n }\\n\\n /**\\n * @notice Queries the owner of the proxy contract.\\n *\\n * @return owner address.\\n */\\n function _getAdmin() internal view returns (address) {\\n address owner;\\n assembly {\\n owner := sload(OWNER_KEY)\\n }\\n return owner;\\n }\\n\\n /**\\n * @notice Performs the proxy call via a delegatecall.\\n */\\n function _doProxyCall() internal {\\n address implementation = _getImplementation();\\n\\n require(implementation != address(0), \\\"Proxy: implementation not initialized\\\");\\n\\n assembly {\\n // Copy calldata into memory at 0x0....calldatasize.\\n calldatacopy(0x0, 0x0, calldatasize())\\n\\n // Perform the delegatecall, make sure to pass all available gas.\\n let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)\\n\\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\\n // overwrite the calldata that we just copied into memory but that doesn't really\\n // matter because we'll be returning in a second anyway.\\n returndatacopy(0x0, 0x0, returndatasize())\\n\\n // Success == 0 means a revert. We'll revert too and pass the data up.\\n if iszero(success) {\\n revert(0x0, returndatasize())\\n }\\n\\n // Otherwise we'll just return and pass the data up.\\n return(0x0, returndatasize())\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2a6719fd9a11adf0efba0243e5c68d56b255296b84cc82bd39326c902e055077\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506040516108ac3803806108ac83398101604081905261002f916100b2565b6100388161003e565b506100e2565b600061005660008051602061088c8339815191525490565b60008051602061088c833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b61079b806100f16000396000f3fe60806040526004361061005a5760003560e01c80635c60da1b116100435780635c60da1b146100ad5780638f283970146100e7578063f851a440146101075761005a565b80633659cfe6146100645780634f1ef28614610084575b61006261011c565b005b34801561007057600080fd5b5061006261007f366004610644565b610212565b61009761009236600461065f565b610284565b6040516100a491906106e2565b60405180910390f35b3480156100b957600080fd5b506100c2610384565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a4565b3480156100f357600080fd5b50610062610102366004610644565b61041b565b34801561011357600080fd5b506100c2610482565b60006101467f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166101ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a6564000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b3660008037600080366000845af43d6000803e8061020c573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061026b575033155b1561027c576102798161050e565b50565b61027961011c565b60606102ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102e5575033155b15610375576102f38461050e565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161031d929190610755565b600060405180830381855af49150503d8060008114610358576040519150601f19603f3d011682016040523d82523d6000602084013e61035d565b606091505b50915091508161036c57600080fd5b915061037d9050565b61037d61011c565b9392505050565b60006103ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103e5575033155b1561041057507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b61041861011c565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610474575033155b1561027c5761027981610576565b60006104ac7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104e3575033155b1561041057507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006105a07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461063f57600080fd5b919050565b60006020828403121561065657600080fd5b61037d8261061b565b60008060006040848603121561067457600080fd5b61067d8461061b565b9250602084013567ffffffffffffffff8082111561069a57600080fd5b818601915086601f8301126106ae57600080fd5b8135818111156106bd57600080fd5b8760208285010111156106cf57600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b8181101561070f578581018301518582016040015282016106f3565b81811115610721576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea264697066735822122002cf23bcc281eec5c701686c2374a3972d766187632ccdd7ca1fe3d13cb4866264736f6c63430008090033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005a5760003560e01c80635c60da1b116100435780635c60da1b146100ad5780638f283970146100e7578063f851a440146101075761005a565b80633659cfe6146100645780634f1ef28614610084575b61006261011c565b005b34801561007057600080fd5b5061006261007f366004610644565b610212565b61009761009236600461065f565b610284565b6040516100a491906106e2565b60405180910390f35b3480156100b957600080fd5b506100c2610384565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a4565b3480156100f357600080fd5b50610062610102366004610644565b61041b565b34801561011357600080fd5b506100c2610482565b60006101467f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166101ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a6564000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b3660008037600080366000845af43d6000803e8061020c573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061026b575033155b1561027c576102798161050e565b50565b61027961011c565b60606102ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102e5575033155b15610375576102f38461050e565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161031d929190610755565b600060405180830381855af49150503d8060008114610358576040519150601f19603f3d011682016040523d82523d6000602084013e61035d565b606091505b50915091508161036c57600080fd5b915061037d9050565b61037d61011c565b9392505050565b60006103ae7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103e5575033155b1561041057507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b61041861011c565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610474575033155b1561027c5761027981610576565b60006104ac7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104e3575033155b1561041057507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006105a07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461063f57600080fd5b919050565b60006020828403121561065657600080fd5b61037d8261061b565b60008060006040848603121561067457600080fd5b61067d8461061b565b9250602084013567ffffffffffffffff8082111561069a57600080fd5b818601915086601f8301126106ae57600080fd5b8135818111156106bd57600080fd5b8760208285010111156106cf57600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b8181101561070f578581018301518582016040015282016106f3565b81811115610721576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea264697066735822122002cf23bcc281eec5c701686c2374a3972d766187632ccdd7ca1fe3d13cb4866264736f6c63430008090033", - "devdoc": { - "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" - } - } - }, - "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 owner. The owner has the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "The address of the implementation contract" - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "The calldata to delegatecall the new implementation with", - "_implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy", - "version": 1 - }, - "userdoc": { - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP 1967 spec." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP 1967 spec." - } - }, - "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": "set the initial owner during contract deployment. The owner is stored at the eip1967 owner storage slot so that storage collision with the implementation is not possible." - }, - "implementation()": { - "notice": "Queries the implementation address." - }, - "upgradeTo(address)": { - "notice": "Set the implementation contract address. The code at this address will execute when this contract is called." - }, - "upgradeToAndCall(address,bytes)": { - "notice": "Set the implementation and call a function in a single transaction. This is useful to ensure atomic `initialize()` based upgrades." - } - }, - "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 offchain simulation.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism-kovan/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json b/packages/contracts-periphery/deployments/optimism-kovan/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json new file mode 100644 index 0000000000000..91d5f99068af8 --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism-kovan/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json @@ -0,0 +1,173 @@ +{ + "language": "Solidity", + "sources": { + "contracts/L1/L1ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L1ERC721Bridge\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as an escrow for ERC721 tokens deposited into L2.\n */\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\n * by ID was deposited for a given L2 token.\n */\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\n * execute any code on L2 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L1ERC721Bridge: local token cannot be self\");\n\n // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\n require(\n deposits[_localToken][_remoteToken][_tokenId] == true,\n \"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\"\n );\n\n // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\n // Bridge.\n deposits[_localToken][_remoteToken][_tokenId] = false;\n\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\n // withdrawer.\n IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\n bytes memory message = abi.encodeWithSelector(\n L2ERC721Bridge.finalizeBridgeERC721.selector,\n _remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Lock token into bridge\n deposits[_localToken][_remoteToken][_tokenId] = true;\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\n\n // Send calldata into L2\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "contracts/universal/op-erc721/ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n CrossDomainMessenger\n} from \"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title ERC721Bridge\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\n */\nabstract contract ERC721Bridge {\n /**\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable messenger;\n\n /**\n * @notice Address of the bridge on the other network.\n */\n address public immutable otherBridge;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[49] private __gap;\n\n /**\n * @notice Ensures that the caller is a cross-chain message from the other bridge.\n */\n modifier onlyOtherBridge() {\n require(\n msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\n \"ERC721Bridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge) {\n require(_messenger != address(0), \"ERC721Bridge: messenger cannot be address(0)\");\n require(_otherBridge != address(0), \"ERC721Bridge: other bridge cannot be address(0)\");\n\n messenger = CrossDomainMessenger(_messenger);\n otherBridge = _otherBridge;\n }\n\n /**\n * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\n * this function can only be called by EOAs. Smart contract wallets should use the\n * `bridgeERC721To` function after ensuring that the recipient address on the remote\n * chain exists. Also note that the current owner of the token on this chain must\n * approve this contract to operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721(\n address _localToken,\n address _remoteToken,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n // Modifier requiring sender to be EOA. This prevents against a user error that would occur\n // if the sender is a smart contract wallet that has a different address on the remote chain\n // (or doesn't have an address on the remote chain at all). The user would fail to receive\n // the NFT if they use this function because it sends the NFT to the same address as the\n // caller. This check could be bypassed by a malicious contract via initcode, but it takes\n // care of the user error we want to avoid.\n require(!Address.isContract(msg.sender), \"ERC721Bridge: account is not externally owned\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\n * that the current owner of the token on this chain must approve this contract to\n * operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n require(_to != address(0), \"ERC721Bridge: nft recipient cannot be address(0)\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Internal function for initiating a token bridge to the other domain.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _from Address of the sender on this domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other domain. Data supplied here will\n * not be used to execute any code on the other domain and is only emitted\n * as extra data for the convenience of off-chain tooling.\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal virtual;\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "contracts/L2/L2ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/op-erc721/IOptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L2ERC721Bridge\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\n * This contract also acts as a burner for tokens being withdrawn.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n */\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\n * execute any code on L1 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L2ERC721Bridge: local token cannot be self\");\n\n // Note that supportsInterface makes a callback to the _localToken address which is user\n // provided.\n require(\n ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\n \"L2ERC721Bridge: local token interface is not compliant\"\n );\n\n require(\n _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\n \"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\"\n );\n\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\n // on L2. Note that safeMint makes a callback to the _to address which is user provided.\n IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Check that the withdrawal is being initiated by the NFT owner\n require(\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\n \"Withdrawal is not being initiated by NFT owner\"\n );\n\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\n // slither-disable-next-line reentrancy-events\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\n require(\n remoteToken == _remoteToken,\n \"L2ERC721Bridge: remote token does not match given value\"\n );\n\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\n // usage\n // slither-disable-next-line reentrancy-events\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\n\n bytes memory message = abi.encodeWithSelector(\n L1ERC721Bridge.finalizeBridgeERC721.selector,\n remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Send message to L1 bridge\n // slither-disable-next-line reentrancy-events\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\n\n/**\n * @title Semver\n * @notice Semver is a simple contract for managing contract versions.\n */\ncontract Semver {\n /**\n * @notice Contract version number (major).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable PATCH_VERSION;\n\n /**\n * @param _major Version number (major).\n * @param _minor Version number (minor).\n * @param _patch Version number (patch).\n */\n constructor(\n uint256 _major,\n uint256 _minor,\n uint256 _patch\n ) {\n MAJOR_VERSION = _major;\n MINOR_VERSION = _minor;\n PATCH_VERSION = _patch;\n }\n\n /**\n * @notice Returns the full semver contract version.\n *\n * @return Semver contract version as a string.\n */\n function version() public view returns (string memory) {\n return\n string(\n abi.encodePacked(\n Strings.toString(MAJOR_VERSION),\n \".\",\n Strings.toString(MINOR_VERSION),\n \".\",\n Strings.toString(PATCH_VERSION)\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n PausableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {\n ReentrancyGuardUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * libAddressManager variable used to exist. Must be the first contract in the inheritance\n * tree of the CrossDomainMessenger\n */\ncontract CrossDomainMessengerLegacySpacer {\n /**\n * @custom:legacy\n * @custom:spacer libAddressManager\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n}\n\n/**\n * @custom:upgradeable\n * @title CrossDomainMessenger\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\n * cross-chain messenger contracts. It's designed to be a universal interface that only\n * needs to be extended slightly to provide low-level message passing functionality on each\n * chain it's deployed on. Currently only designed for message passing between two paired\n * chains and does not support one-to-many interactions.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer,\n OwnableUpgradeable,\n PausableUpgradeable,\n ReentrancyGuardUpgradeable\n{\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Constant overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\n\n /**\n * @notice Numerator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\n\n /**\n * @notice Denominator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\n\n /**\n * @notice Extra gas added to base gas for each byte of calldata in a message.\n */\n uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Minimum amount of gas required to relay a message.\n */\n uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\n\n /**\n * @notice Amount of gas held in reserve to guarantee that relay execution completes.\n */\n uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\n\n /**\n * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\n * because performing an SSTORE on a non-zero value is significantly cheaper than on a\n * zero value.\n */\n address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable otherMessenger;\n\n /**\n * @custom:legacy\n * @custom:spacer blockedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_201_0_32;\n\n /**\n * @custom:legacy\n * @custom:spacer relayedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_202_0_32;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it has successfully been relayed on this chain, and\n * can therefore not be relayed again.\n */\n mapping(bytes32 => bool) public successfulMessages;\n\n /**\n * @notice Address of the sender of the currently executing message on the other chain. If the\n * value of this variable is the default value (0x00000000...dead) then no message is\n * currently being executed. Use the xDomainMessageSender getter which will throw an\n * error if this is the case.\n */\n address internal xDomainMsgSender;\n\n /**\n * @notice Nonce for the next message to be sent, without the message version applied. Use the\n * messageNonce getter which will insert the message version into the nonce to give you\n * the actual nonce to be used for the message.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it failed to be relayed on this chain at least once.\n * If a message is successfully relayed on the first attempt, then it will only be\n * present within the successfulMessages mapping.\n */\n mapping(bytes32 => bool) public receivedMessages;\n\n /**\n * @notice Reserve extra slots in the storage layout for future upgrades.\n * A gap size of 41 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[42] private __gap;\n\n /**\n * @notice Emitted whenever a message is sent to the other chain.\n *\n * @param target Address of the recipient of the message.\n * @param sender Address of the sender of the message.\n * @param message Message to trigger the recipient address with.\n * @param messageNonce Unique nonce attached to the message.\n * @param gasLimit Minimum gas limit that the message can be executed with.\n */\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n /**\n * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\n * SentMessage event without breaking the ABI of this contract, this is good enough.\n *\n * @param sender Address of the sender of the message.\n * @param value ETH value sent along with the message to the recipient.\n */\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n /**\n * @notice Emitted whenever a message is successfully relayed on this chain.\n *\n * @param msgHash Hash of the message that was relayed.\n */\n event RelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @notice Emitted whenever a message fails to be relayed on this chain.\n *\n * @param msgHash Hash of the message that failed to be relayed.\n */\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @param _otherMessenger Address of the messenger on the paired chain.\n */\n constructor(address _otherMessenger) {\n otherMessenger = _otherMessenger;\n }\n\n /**\n * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\n * security mechanism just in case. Owner should be the same as the upgrade wallet to\n * maintain the security model of the system as a whole.\n */\n function pause() external onlyOwner {\n _pause();\n }\n\n /**\n * @notice Allows the owner of this contract to resume message relaying once paused.\n */\n function unpause() external onlyOwner {\n _unpause();\n }\n\n /**\n * @notice Sends a message to some target address on the other chain. Note that if the call\n * always reverts, then the message will be unrelayable, and any ETH sent will be\n * permanently locked. The same will occur if the target on the other chain is\n * considered unsafe (see the _isUnsafeTarget() function).\n *\n * @param _target Target contract or wallet address.\n * @param _message Message to trigger the target address with.\n * @param _minGasLimit Minimum gas limit that the message can be executed with.\n */\n function sendMessage(\n address _target,\n bytes calldata _message,\n uint32 _minGasLimit\n ) external payable {\n // Triggers a message to the other messenger. Note that the amount of gas provided to the\n // message is the amount of gas requested by the user PLUS the base gas value. We want to\n // guarantee the property that the call to the target contract will always have at least\n // the minimum gas limit specified by the user.\n _sendMessage(\n otherMessenger,\n baseGas(_message, _minGasLimit),\n msg.value,\n abi.encodeWithSelector(\n this.relayMessage.selector,\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _minGasLimit,\n _message\n )\n );\n\n emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\n emit SentMessageExtension1(msg.sender, msg.value);\n\n unchecked {\n ++msgNonce;\n }\n }\n\n /**\n * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\n * be executed via cross-chain call from the other messenger OR if the message was\n * already received once and is currently being replayed.\n *\n * @param _nonce Nonce of the message being relayed.\n * @param _sender Address of the user who sent the message.\n * @param _target Address that the message is targeted at.\n * @param _value ETH value to send with the message.\n * @param _minGasLimit Minimum amount of gas that the message can be executed with.\n * @param _message Message to send to the target.\n */\n function relayMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _minGasLimit,\n bytes calldata _message\n ) external payable nonReentrant whenNotPaused {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n\n // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\n // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\n // to the value or minGasLimit fields, which can create unexpected issues for end-users.\n require(\n version == 1,\n \"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\"\n );\n\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n if (_isOtherMessenger()) {\n // This property should always hold when the message is first submitted (as opposed to\n // being replayed).\n assert(msg.value == _value);\n } else {\n require(\n msg.value == 0,\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n\n require(\n receivedMessages[versionedHash],\n \"CrossDomainMessenger: message cannot be replayed\"\n );\n }\n\n require(\n _isUnsafeTarget(_target) == false,\n \"CrossDomainMessenger: cannot send message to blocked system address\"\n );\n\n require(\n successfulMessages[versionedHash] == false,\n \"CrossDomainMessenger: message has already been relayed\"\n );\n\n require(\n gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\n \"CrossDomainMessenger: insufficient gas to relay message\"\n );\n\n xDomainMsgSender = _sender;\n bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n\n if (success == true) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n receivedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n }\n }\n\n /**\n * @notice Retrieves the address of the contract or wallet that initiated the currently\n * executing message on the other chain. Will throw an error if there is no message\n * currently being executed. Allows the recipient of a call to see who triggered it.\n *\n * @return Address of the sender of the currently executing message on the other chain.\n */\n function xDomainMessageSender() external view returns (address) {\n require(\n xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\n \"CrossDomainMessenger: xDomainMessageSender is not set\"\n );\n\n return xDomainMsgSender;\n }\n\n /**\n * @notice Retrieves the next message nonce. Message version will be added to the upper two\n * bytes of the message nonce. Message version allows us to treat messages as having\n * different structures.\n *\n * @return Nonce of the next message to be sent, with added message version.\n */\n function messageNonce() public view returns (uint256) {\n return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\n }\n\n /**\n * @notice Computes the amount of gas required to guarantee that a given message will be\n * received on the other chain without running out of gas. Guaranteeing that a message\n * will not run out of gas is important because this ensures that a message can always\n * be replayed on the other chain if it fails to execute completely.\n *\n * @param _message Message to compute the amount of required gas for.\n * @param _minGasLimit Minimum desired gas limit when message goes to target.\n *\n * @return Amount of gas required to guarantee message receipt.\n */\n function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\n return\n // Dynamic overhead\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\n // Constant overhead\n MIN_GAS_CONSTANT_OVERHEAD;\n }\n\n /**\n * @notice Intializer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __CrossDomainMessenger_init() internal onlyInitializing {\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n __ReentrancyGuard_init_unchained();\n }\n\n /**\n * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @param _to Recipient of the message on the other chain.\n * @param _gasLimit Minimum gas limit the message can be executed with.\n * @param _value Amount of ETH to send with the message.\n * @param _data Message data.\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal virtual;\n\n /**\n * @notice Checks whether the message is coming from the other messenger. Implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @return Whether the message is coming from the other messenger.\n */\n function _isOtherMessenger() internal view virtual returns (bool);\n\n /**\n * @notice Checks whether a given call target is a system address that could cause the\n * messenger to peform an unsafe action. This is NOT a mechanism for blocking user\n * addresses. This is ONLY used to prevent the execution of messages to specific\n * system addresses that could cause security issues, e.g., having the\n * CrossDomainMessenger send messages to itself.\n *\n * @param _target Address of the contract to check.\n *\n * @return Whether or not the address is an unsafe system address.\n */\n function _isUnsafeTarget(address _target) internal view virtual returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title SafeCall\n * @notice Perform low level safe calls\n */\nlibrary SafeCall {\n /**\n * @notice Perform a low level call without copying any returndata\n *\n * @param _target Address to call\n * @param _gas Amount of gas to pass to the call\n * @param _value Amount of value to pass to the call\n * @param _calldata Calldata to pass to the call\n */\n function call(\n address _target,\n uint256 _gas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n assembly {\n _success := call(\n _gas, // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Encoding } from \"./Encoding.sol\";\n\n/**\n * @title Hashing\n * @notice Hashing handles Optimism's various different hashing schemes.\n */\nlibrary Hashing {\n /**\n * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\n * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\n * system.\n *\n * @param _tx User deposit transaction to hash.\n *\n * @return Hash of the RLP encoded L2 deposit transaction.\n */\n function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return keccak256(Encoding.encodeDepositTransaction(_tx));\n }\n\n /**\n * @notice Computes the deposit transaction's \"source hash\", a value that guarantees the hash\n * of the L2 transaction that corresponds to a deposit is unique and is\n * deterministically generated from L1 transaction data.\n *\n * @param _l1BlockHash Hash of the L1 block where the deposit was included.\n * @param _logIndex The index of the log that created the deposit transaction.\n *\n * @return Hash of the deposit transaction's \"source hash\".\n */\n function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\n internal\n pure\n returns (bytes32)\n {\n bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\n return keccak256(abi.encode(bytes32(0), depositId));\n }\n\n /**\n * @notice Hashes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n if (version == 0) {\n return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Hashing: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes32) {\n return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\n }\n\n /**\n * @notice Hashes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n return\n keccak256(\n Encoding.encodeCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n )\n );\n }\n\n /**\n * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\n *\n * @param _tx Withdrawal transaction to hash.\n *\n * @return Hashed withdrawal transaction.\n */\n function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\n );\n }\n\n /**\n * @notice Hashes the various elements of an output root proof into an output root hash which\n * can be used to check if the proof is valid.\n *\n * @param _outputRootProof Output root proof which should hash to an output root.\n *\n * @return Hashed output root proof.\n */\n function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(\n _outputRootProof.version,\n _outputRootProof.stateRoot,\n _outputRootProof.messagePasserStorageRoot,\n _outputRootProof.latestBlockhash\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Hashing } from \"./Hashing.sol\";\nimport { RLPWriter } from \"./rlp/RLPWriter.sol\";\n\n/**\n * @title Encoding\n * @notice Encoding handles Optimism's various different encoding schemes.\n */\nlibrary Encoding {\n /**\n * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\n * to the L2 system. Useful for searching for a deposit in the L2 system. The\n * transaction is prefixed with 0x7e to identify its EIP-2718 type.\n *\n * @param _tx User deposit transaction to encode.\n *\n * @return RLP encoded L2 deposit transaction.\n */\n function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes memory)\n {\n bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\n bytes[] memory raw = new bytes[](8);\n raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\n raw[1] = RLPWriter.writeAddress(_tx.from);\n raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\"\") : RLPWriter.writeAddress(_tx.to);\n raw[3] = RLPWriter.writeUint(_tx.mint);\n raw[4] = RLPWriter.writeUint(_tx.value);\n raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\n raw[6] = RLPWriter.writeBool(false);\n raw[7] = RLPWriter.writeBytes(_tx.data);\n return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\n }\n\n /**\n * @notice Encodes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n (, uint16 version) = decodeVersionedNonce(_nonce);\n if (version == 0) {\n return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Encoding: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _data,\n _nonce\n );\n }\n\n /**\n * @notice Encodes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(uint256,address,address,uint256,uint256,bytes)\",\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n }\n\n /**\n * @notice Adds a version number into the first two bytes of a message nonce.\n *\n * @param _nonce Message nonce to encode into.\n * @param _version Version number to encode into the message nonce.\n *\n * @return Message nonce with version encoded into the first two bytes.\n */\n function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\n uint256 nonce;\n assembly {\n nonce := or(shl(240, _version), _nonce)\n }\n return nonce;\n }\n\n /**\n * @notice Pulls the version out of a version-encoded nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n *\n * @return Nonce without encoded version.\n * @return Version of the message.\n */\n function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\n uint240 nonce;\n uint16 version;\n assembly {\n nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n version := shr(240, _nonce)\n }\n return (nonce, version);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Types\n * @notice Contains various types used throughout the Optimism contract system.\n */\nlibrary Types {\n /**\n * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\n * timestamp that the output root is posted. This timestamp is used to verify that the\n * finalization period has passed since the output root was submitted.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint256 timestamp;\n }\n\n /**\n * @notice Struct representing the elements that are hashed together to generate an output root\n * which itself represents a snapshot of the L2 state.\n */\n struct OutputRootProof {\n bytes32 version;\n bytes32 stateRoot;\n bytes32 messagePasserStorageRoot;\n bytes32 latestBlockhash;\n }\n\n /**\n * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\n * user (as opposed to a system deposit transaction generated by the system).\n */\n struct UserDepositTransaction {\n address from;\n address to;\n bool isCreation;\n uint256 value;\n uint256 mint;\n uint64 gasLimit;\n bytes data;\n bytes32 l1BlockHash;\n uint256 logIndex;\n }\n\n /**\n * @notice Struct representing a withdrawal transaction.\n */\n struct WithdrawalTransaction {\n uint256 nonce;\n address sender;\n address target;\n uint256 value;\n uint256 gasLimit;\n bytes data;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\n * @title RLPWriter\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\n * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\n * modifications to improve legibility.\n */\nlibrary RLPWriter {\n /**\n * @notice RLP encodes a byte string.\n *\n * @param _in The byte string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_in.length == 1 && uint8(_in[0]) < 128) {\n encoded = _in;\n } else {\n encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\n }\n\n return encoded;\n }\n\n /**\n * @notice RLP encodes a list of RLP encoded byte byte strings.\n *\n * @param _in The list of RLP encoded byte strings.\n *\n * @return The RLP encoded list of items in bytes.\n */\n function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\n bytes memory list = _flatten(_in);\n return abi.encodePacked(_writeLength(list.length, 192), list);\n }\n\n /**\n * @notice RLP encodes a string.\n *\n * @param _in The string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeString(string memory _in) internal pure returns (bytes memory) {\n return writeBytes(bytes(_in));\n }\n\n /**\n * @notice RLP encodes an address.\n *\n * @param _in The address to encode.\n *\n * @return The RLP encoded address in bytes.\n */\n function writeAddress(address _in) internal pure returns (bytes memory) {\n return writeBytes(abi.encodePacked(_in));\n }\n\n /**\n * @notice RLP encodes a uint.\n *\n * @param _in The uint256 to encode.\n *\n * @return The RLP encoded uint256 in bytes.\n */\n function writeUint(uint256 _in) internal pure returns (bytes memory) {\n return writeBytes(_toBinary(_in));\n }\n\n /**\n * @notice RLP encodes a bool.\n *\n * @param _in The bool to encode.\n *\n * @return The RLP encoded bool in bytes.\n */\n function writeBool(bool _in) internal pure returns (bytes memory) {\n bytes memory encoded = new bytes(1);\n encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n return encoded;\n }\n\n /**\n * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\n *\n * @param _len The length of the string or the payload.\n * @param _offset 128 if item is string, 192 if item is list.\n *\n * @return RLP encoded bytes.\n */\n function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_len < 56) {\n encoded = new bytes(1);\n encoded[0] = bytes1(uint8(_len) + uint8(_offset));\n } else {\n uint256 lenLen;\n uint256 i = 1;\n while (_len / i != 0) {\n lenLen++;\n i *= 256;\n }\n\n encoded = new bytes(lenLen + 1);\n encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\n for (i = 1; i <= lenLen; i++) {\n encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\n }\n }\n\n return encoded;\n }\n\n /**\n * @notice Encode integer in big endian binary form with no leading zeroes.\n *\n * @param _x The integer to encode.\n *\n * @return RLP encoded bytes.\n */\n function _toBinary(uint256 _x) private pure returns (bytes memory) {\n bytes memory b = abi.encodePacked(_x);\n\n uint256 i = 0;\n for (; i < 32; i++) {\n if (b[i] != 0) {\n break;\n }\n }\n\n bytes memory res = new bytes(32 - i);\n for (uint256 j = 0; j < res.length; j++) {\n res[j] = b[i++];\n }\n\n return res;\n }\n\n /**\n * @custom:attribution https://github.com/Arachnid/solidity-stringutils\n * @notice Copies a piece of memory to another location.\n *\n * @param _dest Destination location.\n * @param _src Source location.\n * @param _len Length of memory to copy.\n */\n function _memcpy(\n uint256 _dest,\n uint256 _src,\n uint256 _len\n ) private pure {\n uint256 dest = _dest;\n uint256 src = _src;\n uint256 len = _len;\n\n for (; len >= 32; len -= 32) {\n assembly {\n mstore(dest, mload(src))\n }\n dest += 32;\n src += 32;\n }\n\n uint256 mask;\n unchecked {\n mask = 256**(32 - len) - 1;\n }\n assembly {\n let srcpart := and(mload(src), not(mask))\n let destpart := and(mload(dest), mask)\n mstore(dest, or(destpart, srcpart))\n }\n }\n\n /**\n * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\n * @notice Flattens a list of byte strings into one byte string.\n *\n * @param _list List of byte strings to flatten.\n *\n * @return The flattened byte string.\n */\n function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\n if (_list.length == 0) {\n return new bytes(0);\n }\n\n uint256 len;\n uint256 i = 0;\n for (; i < _list.length; i++) {\n len += _list[i].length;\n }\n\n bytes memory flattened = new bytes(len);\n uint256 flattenedPtr;\n assembly {\n flattenedPtr := add(flattened, 0x20)\n }\n\n for (i = 0; i < _list.length; i++) {\n bytes memory item = _list[i];\n\n uint256 listPtr;\n assembly {\n listPtr := add(item, 0x20)\n }\n\n _memcpy(flattenedPtr, listPtr, item.length);\n flattenedPtr += _list[i].length;\n }\n\n return flattened;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" + }, + "contracts/universal/op-erc721/IOptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n IERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\";\n\n/**\n * @title IOptimismMintableERC721\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\n */\ninterface IOptimismMintableERC721 is IERC721Enumerable {\n /**\n * @notice Emitted when a token is minted.\n *\n * @param account Address of the account the token was minted to.\n * @param tokenId Token ID of the minted token.\n */\n event Mint(address indexed account, uint256 tokenId);\n\n /**\n * @notice Emitted when a token is burned.\n *\n * @param account Address of the account the token was burned from.\n * @param tokenId Token ID of the burned token.\n */\n event Burn(address indexed account, uint256 tokenId);\n\n /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function remoteChainId() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function remoteToken() external view returns (address);\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n function bridge() external view returns (address);\n\n /**\n * @notice Mints some token ID for a user, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * @param _to Address of the user to mint the token for.\n * @param _tokenId Token ID to mint.\n */\n function safeMint(address _to, uint256 _tokenId) external;\n\n /**\n * @notice Burns a token ID from a user.\n *\n * @param _from Address of the user to burn the token from.\n * @param _tokenId Token ID to burn.\n */\n function burn(address _from, uint256 _tokenId) external;\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n /**\n * @dev Returns the total amount of tokens stored by the contract.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n /**\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n * Use along with {totalSupply} to enumerate all tokens.\n */\n function tokenByIndex(uint256 index) external view returns (uint256);\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismMintableERC721 } from \"./OptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC721Factory\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\n */\ncontract OptimismMintableERC721Factory is Semver {\n /**\n * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\n *\n * @param localToken Address of the token on the this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param deployer Address of the initiator of the deployment\n */\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n address public immutable bridge;\n\n /**\n * @notice Chain ID for the remote network.\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 0, 0) {\n require(\n _bridge != address(0),\n \"OptimismMintableERC721Factory: bridge cannot be address(0)\"\n );\n require(\n _remoteChainId != 0,\n \"OptimismMintableERC721Factory: remote chain id cannot be zero\"\n );\n\n bridge = _bridge;\n remoteChainId = _remoteChainId;\n }\n\n /**\n * @notice Creates an instance of the standard ERC721.\n *\n * @param _remoteToken Address of the corresponding token on the other domain.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n function createOptimismMintableERC721(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721Factory: L1 token address cannot be address(0)\"\n );\n\n address localToken = address(\n new OptimismMintableERC721(bridge, remoteChainId, _remoteToken, _name, _symbol)\n );\n\n isOptimismMintableERC721[localToken] = true;\n emit OptimismMintableERC721Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n ERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { IOptimismMintableERC721 } from \"./IOptimismMintableERC721.sol\";\n\n/**\n * @title OptimismMintableERC721\n * @notice This contract is the remote representation for some token that lives on another network,\n * typically an Optimism representation of an Ethereum-based token. Standard reference\n * implementation that can be extended or modified according to your needs.\n */\ncontract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable remoteToken;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable bridge;\n\n /**\n * @notice Base token URI for this token.\n */\n string public baseTokenURI;\n\n /**\n * @param _bridge Address of the bridge on this network.\n * @param _remoteChainId Chain ID where the remote token is deployed.\n * @param _remoteToken Address of the corresponding token on the other network.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n constructor(\n address _bridge,\n uint256 _remoteChainId,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC721(_name, _symbol) {\n require(_bridge != address(0), \"OptimismMintableERC721: bridge cannot be address(0)\");\n require(_remoteChainId != 0, \"OptimismMintableERC721: remote chain id cannot be zero\");\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721: remote token cannot be address(0)\"\n );\n\n remoteChainId = _remoteChainId;\n remoteToken = _remoteToken;\n bridge = _bridge;\n\n // Creates a base URI in the format specified by EIP-681:\n // https://eips.ethereum.org/EIPS/eip-681\n baseTokenURI = string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(_remoteToken), 20),\n \"@\",\n Strings.toString(_remoteChainId),\n \"/tokenURI?uint256=\"\n )\n );\n }\n\n /**\n * @notice Modifier that prevents callers other than the bridge from calling the function.\n */\n modifier onlyBridge() {\n require(msg.sender == bridge, \"OptimismMintableERC721: only bridge can call this function\");\n _;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {\n _safeMint(_to, _tokenId);\n\n emit Mint(_to, _tokenId);\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function burn(address _from, uint256 _tokenId) external virtual onlyBridge {\n _burn(_tokenId);\n\n emit Burn(_from, _tokenId);\n }\n\n /**\n * @notice Checks if a given interface ID is supported by this contract.\n *\n * @param _interfaceId The interface ID to check.\n *\n * @return True if the interface ID is supported, false otherwise.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n override(ERC721Enumerable, IERC165)\n returns (bool)\n {\n bytes4 iface1 = type(IERC165).interfaceId;\n bytes4 iface2 = type(IOptimismMintableERC721).interfaceId;\n return\n _interfaceId == iface1 ||\n _interfaceId == iface2 ||\n super.supportsInterface(_interfaceId);\n }\n\n /**\n * @notice Returns the base token URI.\n *\n * @return Base token URI.\n */\n function _baseURI() internal view virtual override returns (string memory) {\n return baseTokenURI;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721.sol\";\nimport \"./IERC721Enumerable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\n // Mapping from owner to list of owned token IDs\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n // Mapping from token ID to index of the owner tokens list\n mapping(uint256 => uint256) private _ownedTokensIndex;\n\n // Array with all token ids, used for enumeration\n uint256[] private _allTokens;\n\n // Mapping from token id to position in the allTokens array\n mapping(uint256 => uint256) private _allTokensIndex;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721.balanceOf(owner), \"ERC721Enumerable: owner index out of bounds\");\n return _ownedTokens[owner][index];\n }\n\n /**\n * @dev See {IERC721Enumerable-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _allTokens.length;\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenByIndex}.\n */\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721Enumerable.totalSupply(), \"ERC721Enumerable: global index out of bounds\");\n return _allTokens[index];\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, tokenId);\n\n if (from == address(0)) {\n _addTokenToAllTokensEnumeration(tokenId);\n } else if (from != to) {\n _removeTokenFromOwnerEnumeration(from, tokenId);\n }\n if (to == address(0)) {\n _removeTokenFromAllTokensEnumeration(tokenId);\n } else if (to != from) {\n _addTokenToOwnerEnumeration(to, tokenId);\n }\n }\n\n /**\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\n * @param to address representing the new owner of the given token ID\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n */\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n uint256 length = ERC721.balanceOf(to);\n _ownedTokens[to][length] = tokenId;\n _ownedTokensIndex[tokenId] = length;\n }\n\n /**\n * @dev Private function to add a token to this extension's token tracking data structures.\n * @param tokenId uint256 ID of the token to be added to the tokens list\n */\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n _allTokensIndex[tokenId] = _allTokens.length;\n _allTokens.push(tokenId);\n }\n\n /**\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n * @param from address representing the previous owner of the given token ID\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n */\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary\n if (tokenIndex != lastTokenIndex) {\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\n\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n }\n\n // This also deletes the contents at the last position of the array\n delete _ownedTokensIndex[tokenId];\n delete _ownedTokens[from][lastTokenIndex];\n }\n\n /**\n * @dev Private function to remove a token from this extension's token tracking data structures.\n * This has O(1) time complexity, but alters the order of the _allTokens array.\n * @param tokenId uint256 ID of the token to be removed from the tokens list\n */\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = _allTokens.length - 1;\n uint256 tokenIndex = _allTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n uint256 lastTokenId = _allTokens[lastTokenIndex];\n\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n // This also deletes the contents at the last position of the array\n delete _allTokensIndex[tokenId];\n _allTokens.pop();\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: balance query for the zero address\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _owners[tokenId];\n require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not owner nor approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n _safeTransfer(from, to, tokenId, _data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _owners[tokenId] != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, _data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId);\n\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId);\n\n // Clear approvals\n _approve(address(0), tokenId);\n\n _balances[owner] -= 1;\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId);\n\n // Clear approvals from the previous owner\n _approve(address(0), tokenId);\n\n _balances[from] -= 1;\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits a {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/AddressManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:legacy\n * @title AddressManager\n * @notice AddressManager is a legacy contract that was used in the old version of the Optimism\n * system to manage a registry of string names to addresses. We now use a more standard\n * proxy system instead, but this contract is still necessary for backwards compatibility\n * with several older contracts.\n */\ncontract AddressManager is Ownable {\n /**\n * @notice Mapping of the hashes of string names to addresses.\n */\n mapping(bytes32 => address) private addresses;\n\n /**\n * @notice Emitted when an address is modified in the registry.\n *\n * @param name String name being set in the registry.\n * @param newAddress Address set for the given name.\n * @param oldAddress Address that was previously set for the given name.\n */\n event AddressSet(string indexed name, address newAddress, address oldAddress);\n\n /**\n * @notice Changes the address associated with a particular name.\n *\n * @param _name String name to associate an address with.\n * @param _address Address to associate with the name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n bytes32 nameHash = _getNameHash(_name);\n address oldAddress = addresses[nameHash];\n addresses[nameHash] = _address;\n\n emit AddressSet(_name, _address, oldAddress);\n }\n\n /**\n * @notice Retrieves the address associated with a given name.\n *\n * @param _name Name to retrieve an address for.\n *\n * @return Address associated with the given name.\n */\n function getAddress(string memory _name) external view returns (address) {\n return addresses[_getNameHash(_name)];\n }\n\n /**\n * @notice Computes the hash of a name.\n *\n * @param _name Name to compute a hash for.\n *\n * @return Hash of the given name.\n */\n function _getNameHash(string memory _name) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(_name));\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\nimport { Proxy } from \"./Proxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\n\n/**\n * @title IStaticERC1967Proxy\n * @notice IStaticERC1967Proxy is a static version of the ERC1967 proxy interface.\n */\ninterface IStaticERC1967Proxy {\n function implementation() external view returns (address);\n\n function admin() external view returns (address);\n}\n\n/**\n * @title IStaticL1ChugSplashProxy\n * @notice IStaticL1ChugSplashProxy is a static version of the ChugSplash proxy interface.\n */\ninterface IStaticL1ChugSplashProxy {\n function getImplementation() external view returns (address);\n\n function getOwner() external view returns (address);\n}\n\n/**\n * @title ProxyAdmin\n * @notice This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy,\n * based on the OpenZeppelin implementation. It has backwards compatibility logic to work\n * with the various types of proxies that have been deployed by Optimism in the past.\n */\ncontract ProxyAdmin is Owned {\n /**\n * @notice The proxy types that the ProxyAdmin can manage.\n *\n * @custom:value ERC1967 Represents an ERC1967 compliant transparent proxy interface.\n * @custom:value CHUGSPLASH Represents the Chugsplash proxy interface (legacy).\n * @custom:value RESOLVED Represents the ResolvedDelegate proxy (legacy).\n */\n enum ProxyType {\n ERC1967,\n CHUGSPLASH,\n RESOLVED\n }\n\n /**\n * @custom:legacy\n * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\n * @custom:legacy\n * @notice A reverse mapping of addresses to names held in the AddressManager. This must be\n * manually kept up to date with changes in the AddressManager for this contract\n * to be able to work as an admin for the ResolvedDelegateProxy type.\n */\n mapping(address => string) public implementationName;\n\n /**\n * @custom:legacy\n * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @custom:legacy\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading = false;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * @notice Sets the proxy type for a given address. Only required for non-standard (legacy)\n * proxy types.\n *\n * @param _address Address of the proxy.\n * @param _type Type of the proxy.\n */\n function setProxyType(address _address, ProxyType _type) external onlyOwner {\n proxyType[_address] = _type;\n }\n\n /**\n * @notice Sets the implementation name for a given address. Only required for\n * ResolvedDelegateProxy type proxies that have an implementation name.\n *\n * @param _address Address of the ResolvedDelegateProxy.\n * @param _name Name of the implementation for the proxy.\n */\n function setImplementationName(address _address, string memory _name) external onlyOwner {\n implementationName[_address] = _name;\n }\n\n /**\n * @notice Set the address of the AddressManager. This is required to manage legacy\n * ResolvedDelegateProxy type proxy contracts.\n *\n * @param _address Address of the AddressManager.\n */\n function setAddressManager(AddressManager _address) external onlyOwner {\n addressManager = _address;\n }\n\n /**\n * @custom:legacy\n * @notice Set an address in the address manager. Since only the owner of the AddressManager\n * can directly modify addresses and the ProxyAdmin will own the AddressManager, this\n * gives the owner of the ProxyAdmin the ability to modify addresses directly.\n *\n * @param _name Name to set within the AddressManager.\n * @param _address Address to attach to the given name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n addressManager.setAddress(_name, _address);\n }\n\n /**\n * @custom:legacy\n * @notice Set the upgrading status for the Chugsplash proxy type.\n *\n * @param _upgrading Whether or not the system is upgrading.\n */\n function setUpgrading(bool _upgrading) external onlyOwner {\n upgrading = _upgrading;\n }\n\n /**\n * @notice Updates the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to update.\n * @param _newAdmin Address of the new proxy admin.\n */\n function changeProxyAdmin(address payable _proxy, address _newAdmin) external onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).changeAdmin(_newAdmin);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setOwner(_newAdmin);\n } else if (ptype == ProxyType.RESOLVED) {\n addressManager.transferOwnership(_newAdmin);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract and delegatecalls the new implementation\n * with some given data. Useful for atomic upgrade-and-initialize calls.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n * @param _data Data to trigger the new implementation with.\n */\n function upgradeAndCall(\n address payable _proxy,\n address _implementation,\n bytes memory _data\n ) external payable onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeToAndCall{ value: msg.value }(_implementation, _data);\n } else {\n // reverts if proxy type is unknown\n upgrade(_proxy, _implementation);\n (bool success, ) = _proxy.call{ value: msg.value }(_data);\n require(success, \"ProxyAdmin: call to proxy after upgrade failed\");\n }\n }\n\n /**\n * @custom:legacy\n * @notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\n *\n * @return Whether or not there is an upgrade going on. May not actually tell you whether an\n * upgrade is going on, since we don't currently plan to use this variable for anything\n * other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\n */\n function isUpgrading() external view returns (bool) {\n return upgrading;\n }\n\n /**\n * @notice Returns the implementation of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the implementation of.\n *\n * @return Address of the implementation of the proxy.\n */\n function getProxyImplementation(address _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).implementation();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getImplementation();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.getAddress(implementationName[_proxy]);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Returns the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the admin of.\n *\n * @return Address of the admin of the proxy.\n */\n function getProxyAdmin(address payable _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).admin();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getOwner();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.owner();\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n */\n function upgrade(address payable _proxy, address _implementation) public onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeTo(_implementation);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setStorage(\n // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,\n bytes32(uint256(uint160(_implementation)))\n );\n } else if (ptype == ProxyType.RESOLVED) {\n string memory name = implementationName[_proxy];\n addressManager.setAddress(name, _implementation);\n } else {\n // It should not be possible to retrieve a ProxyType value which is not matched by\n // one of the previous conditions.\n assert(false);\n }\n }\n}\n" + }, + "@rari-capital/solmate/src/auth/Owned.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol)\nabstract contract Owned {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event OwnerUpdated(address indexed user, address indexed newOwner);\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP STORAGE\n //////////////////////////////////////////////////////////////*/\n\n address public owner;\n\n modifier onlyOwner() virtual {\n require(msg.sender == owner, \"UNAUTHORIZED\");\n\n _;\n }\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(address _owner) {\n owner = _owner;\n\n emit OwnerUpdated(address(0), _owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function setOwner(address newOwner) public virtual onlyOwner {\n owner = newOwner;\n\n emit OwnerUpdated(msg.sender, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Proxy\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\n * if the caller is address(0), meaning that the call originated from an off-chain\n * simulation.\n */\ncontract Proxy {\n /**\n * @notice The storage slot that holds the address of the implementation.\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice The storage slot that holds the address of the owner.\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice An event that is emitted each time the implementation is changed. This event is part\n * of the EIP-1967 specification.\n *\n * @param implementation The address of the implementation contract\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\n * EIP-1967 specification.\n *\n * @param previousAdmin The previous owner of the contract\n * @param newAdmin The new owner of the contract\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\n * eth_call to interact with this proxy without needing to use low-level storage\n * inspection. We assume that nobody is able to trigger calls from address(0) during\n * normal EVM execution.\n */\n modifier proxyCallIfNotAdmin() {\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\n * EIP-1967 admin storage slot so that accidental storage collision with the\n * implementation is not possible.\n *\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\n * transparent proxy interface.\n */\n constructor(address _admin) {\n _changeAdmin(_admin);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Set the implementation contract address. The code at the given address will execute\n * when this contract is called.\n *\n * @param _implementation Address of the implementation contract.\n */\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\n _setImplementation(_implementation);\n }\n\n /**\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\n * atomic execution of initialization-based upgrades.\n *\n * @param _implementation Address of the implementation contract.\n * @param _data Calldata to delegatecall the new implementation with.\n */\n function upgradeToAndCall(address _implementation, bytes calldata _data)\n external\n payable\n proxyCallIfNotAdmin\n returns (bytes memory)\n {\n _setImplementation(_implementation);\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\n require(success, \"Proxy: delegatecall to new implementation contract failed\");\n return returndata;\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _admin New owner of the proxy contract.\n */\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\n _changeAdmin(_admin);\n }\n\n /**\n * @notice Gets the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function admin() external proxyCallIfNotAdmin returns (address) {\n return _getAdmin();\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function implementation() external proxyCallIfNotAdmin returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n emit Upgraded(_implementation);\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _admin New owner of the proxy contract.\n */\n function _changeAdmin(address _admin) internal {\n address previous = _getAdmin();\n assembly {\n sstore(OWNER_KEY, _admin)\n }\n emit AdminChanged(previous, _admin);\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal {\n address impl = _getImplementation();\n require(impl != address(0), \"Proxy: implementation not initialized\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address impl;\n assembly {\n impl := sload(IMPLEMENTATION_KEY)\n }\n return impl;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getAdmin() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/L1ChugSplashProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title IL1ChugSplashDeployer\n */\ninterface IL1ChugSplashDeployer {\n function isUpgrading() external view returns (bool);\n}\n\n/**\n * @custom:legacy\n * @title L1ChugSplashProxy\n * @notice Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added\n * functions `setCode` and `setStorage` for changing the code or storage of the contract.\n *\n * Note for future developers: do NOT make anything in this contract 'public' unless you\n * know what you're doing. Anything public can potentially have a function signature that\n * conflicts with a signature attached to the implementation contract. Public functions\n * SHOULD always have the `proxyCallIfNotOwner` modifier unless there's some *really* good\n * reason not to have that modifier. And there almost certainly is not a good reason to not\n * have that modifier. Beware!\n */\ncontract L1ChugSplashProxy {\n /**\n * @notice \"Magic\" prefix. When prepended to some arbitrary bytecode and used to create a\n * contract, the appended bytecode will be deployed as given.\n */\n bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice Blocks a function from being called when the parent signals that the system should\n * be paused via an isUpgrading function.\n */\n modifier onlyWhenNotPaused() {\n address owner = _getOwner();\n\n // We do a low-level call because there's no guarantee that the owner actually *is* an\n // L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and\n // it turns out that it isn't the right type of contract.\n (bool success, bytes memory returndata) = owner.staticcall(\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector)\n );\n\n // If the call was unsuccessful then we assume that there's no \"isUpgrading\" method and we\n // can just continue as normal. We also expect that the return value is exactly 32 bytes\n // long. If this isn't the case then we can safely ignore the result.\n if (success && returndata.length == 32) {\n // Although the expected value is a *boolean*, it's safer to decode as a uint256 in the\n // case that the isUpgrading function returned something other than 0 or 1. But we only\n // really care about the case where this value is 0 (= false).\n uint256 ret = abi.decode(returndata, (uint256));\n require(ret == 0, \"L1ChugSplashProxy: system is currently being upgraded\");\n }\n\n _;\n }\n\n /**\n * @notice Makes a proxy call instead of triggering the given function when the caller is\n * either the owner or the zero address. Caller can only ever be the zero address if\n * this function is being called off-chain via eth_call, which is totally fine and can\n * be convenient for client-side tooling. Avoids situations where the proxy and\n * implementation share a sighash and the proxy function ends up being called instead\n * of the implementation one.\n *\n * Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If\n * there's a way for someone to send a transaction with msg.sender == address(0) in any\n * real context then we have much bigger problems. Primary reason to include this\n * additional allowed sender is because the owner address can be changed dynamically\n * and we do not want clients to have to keep track of the current owner in order to\n * make an eth_call that doesn't trigger the proxied contract.\n */\n // slither-disable-next-line incorrect-modifier\n modifier proxyCallIfNotOwner() {\n if (msg.sender == _getOwner() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @param _owner Address of the initial contract owner.\n */\n constructor(address _owner) {\n _setOwner(_owner);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Sets the code that should be running behind this proxy.\n *\n * Note: This scheme is a bit different from the standard proxy scheme where one would\n * typically deploy the code separately and then set the implementation address. We're\n * doing it this way because it gives us a lot more freedom on the client side. Can\n * only be triggered by the contract owner.\n *\n * @param _code New contract code to run inside this contract.\n */\n function setCode(bytes memory _code) external proxyCallIfNotOwner {\n // Get the code hash of the current implementation.\n address implementation = _getImplementation();\n\n // If the code hash matches the new implementation then we return early.\n if (keccak256(_code) == _getAccountCodeHash(implementation)) {\n return;\n }\n\n // Create the deploycode by appending the magic prefix.\n bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code);\n\n // Deploy the code and set the new implementation address.\n address newImplementation;\n assembly {\n newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode))\n }\n\n // Check that the code was actually deployed correctly. I'm not sure if you can ever\n // actually fail this check. Should only happen if the contract creation from above runs\n // out of gas but this parent execution thread does NOT run out of gas. Seems like we\n // should be doing this check anyway though.\n require(\n _getAccountCodeHash(newImplementation) == keccak256(_code),\n \"L1ChugSplashProxy: code was not correctly deployed\"\n );\n\n _setImplementation(newImplementation);\n }\n\n /**\n * @notice Modifies some storage slot within the proxy contract. Gives us a lot of power to\n * perform upgrades in a more transparent way. Only callable by the owner.\n *\n * @param _key Storage key to modify.\n * @param _value New value for the storage key.\n */\n function setStorage(bytes32 _key, bytes32 _value) external proxyCallIfNotOwner {\n assembly {\n sstore(_key, _value)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _owner New owner of the proxy contract.\n */\n function setOwner(address _owner) external proxyCallIfNotOwner {\n _setOwner(_owner);\n }\n\n /**\n * @notice Queries the owner of the proxy contract. Can only be called by the owner OR by\n * making an eth_call and setting the \"from\" address to address(0).\n *\n * @return Owner address.\n */\n function getOwner() external proxyCallIfNotOwner returns (address) {\n return _getOwner();\n }\n\n /**\n * @notice Queries the implementation address. Can only be called by the owner OR by making an\n * eth_call and setting the \"from\" address to address(0).\n *\n * @return Implementation address.\n */\n function getImplementation() external proxyCallIfNotOwner returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _owner New owner of the proxy contract.\n */\n function _setOwner(address _owner) internal {\n assembly {\n sstore(OWNER_KEY, _owner)\n }\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal onlyWhenNotPaused {\n address implementation = _getImplementation();\n\n require(implementation != address(0), \"L1ChugSplashProxy: implementation is not set yet\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address implementation;\n assembly {\n implementation := sload(IMPLEMENTATION_KEY)\n }\n return implementation;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getOwner() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n\n /**\n * @notice Gets the code hash for a given account.\n *\n * @param _account Address of the account to get a code hash for.\n *\n * @return Code hash for the account.\n */\n function _getAccountCodeHash(address _account) internal view returns (bytes32) {\n bytes32 codeHash;\n assembly {\n codeHash := extcodehash(_account)\n }\n return codeHash;\n }\n}\n" + }, + "contracts/testing/helpers/ExternalContractCompiler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ProxyAdmin } from \"@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol\";\nimport { Proxy } from \"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\";\n\n/**\n * Just exists so we can compile external contracts.\n */\ncontract ExternalContractCompiler {\n\n}\n" + }, + "contracts/testing/helpers/TestERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\n\ncontract TestERC721 is ERC721 {\n constructor() ERC721(\"TEST\", \"TST\") {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n\n function tokenURI(uint256) public pure virtual override returns (string memory) {}\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 indexed id);\n\n event Approval(address indexed owner, address indexed spender, uint256 indexed id);\n\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE/LOGIC\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n function tokenURI(uint256 id) public view virtual returns (string memory);\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) internal _ownerOf;\n\n mapping(address => uint256) internal _balanceOf;\n\n function ownerOf(uint256 id) public view virtual returns (address owner) {\n require((owner = _ownerOf[id]) != address(0), \"NOT_MINTED\");\n }\n\n function balanceOf(address owner) public view virtual returns (uint256) {\n require(owner != address(0), \"ZERO_ADDRESS\");\n\n return _balanceOf[owner];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) public getApproved;\n\n mapping(address => mapping(address => bool)) public isApprovedForAll;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(string memory _name, string memory _symbol) {\n name = _name;\n symbol = _symbol;\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 id) public virtual {\n address owner = _ownerOf[id];\n\n require(msg.sender == owner || isApprovedForAll[owner][msg.sender], \"NOT_AUTHORIZED\");\n\n getApproved[id] = spender;\n\n emit Approval(owner, spender, id);\n }\n\n function setApprovalForAll(address operator, bool approved) public virtual {\n isApprovedForAll[msg.sender][operator] = approved;\n\n emit ApprovalForAll(msg.sender, operator, approved);\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n require(from == _ownerOf[id], \"WRONG_FROM\");\n\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(\n msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],\n \"NOT_AUTHORIZED\"\n );\n\n // Underflow of the sender's balance is impossible because we check for\n // ownership above and the recipient's balance can't realistically overflow.\n unchecked {\n _balanceOf[from]--;\n\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n delete getApproved[id];\n\n emit Transfer(from, to, id);\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n bytes calldata data\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return\n interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165\n interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721\n interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 id) internal virtual {\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(_ownerOf[id] == address(0), \"ALREADY_MINTED\");\n\n // Counter overflow is incredibly unrealistic.\n unchecked {\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n emit Transfer(address(0), to, id);\n }\n\n function _burn(uint256 id) internal virtual {\n address owner = _ownerOf[id];\n\n require(owner != address(0), \"NOT_MINTED\");\n\n // Ownership check above ensures no underflow.\n unchecked {\n _balanceOf[owner]--;\n }\n\n delete _ownerOf[id];\n\n delete getApproved[id];\n\n emit Transfer(owner, address(0), id);\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL SAFE MINT LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _safeMint(address to, uint256 id) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function _safeMint(\n address to,\n uint256 id,\n bytes memory data\n ) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n}\n\n/// @notice A generic interface for a contract which properly accepts ERC721 tokens.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721TokenReceiver {\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n ) external virtual returns (bytes4) {\n return ERC721TokenReceiver.onERC721Received.selector;\n }\n}\n" + }, + "contracts/testing/helpers/TestERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n constructor() ERC20(\"TEST\", \"TST\", 18) {}\n\n function mint(address to, uint256 value) public {\n _mint(to, value);\n }\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "contracts/L1/TeleportrWithdrawer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AssetReceiver } from \"../universal/AssetReceiver.sol\";\n\n/**\n * @notice Stub interface for Teleportr.\n */\ninterface Teleportr {\n function withdrawBalance() external;\n}\n\n/**\n * @title TeleportrWithdrawer\n * @notice The TeleportrWithdrawer is a simple contract capable of withdrawing funds from the\n * TeleportrContract and sending them to some recipient address.\n */\ncontract TeleportrWithdrawer is AssetReceiver {\n /**\n * @notice Address of the Teleportr contract.\n */\n address public teleportr;\n\n /**\n * @notice Address that will receive Teleportr withdrawals.\n */\n address public recipient;\n\n /**\n * @notice Data to be sent to the recipient address.\n */\n bytes public data;\n\n /**\n * @param _owner Initial owner of the contract.\n */\n constructor(address _owner) AssetReceiver(_owner) {}\n\n /**\n * @notice Allows the owner to update the recipient address.\n *\n * @param _recipient New recipient address.\n */\n function setRecipient(address _recipient) external onlyOwner {\n recipient = _recipient;\n }\n\n /**\n * @notice Allows the owner to update the Teleportr contract address.\n *\n * @param _teleportr New Teleportr contract address.\n */\n function setTeleportr(address _teleportr) external onlyOwner {\n teleportr = _teleportr;\n }\n\n /**\n * @notice Allows the owner to update the data to be sent to the recipient address.\n *\n * @param _data New data to be sent to the recipient address.\n */\n function setData(bytes memory _data) external onlyOwner {\n data = _data;\n }\n\n /**\n * @notice Withdraws the full balance of the Teleportr contract to the recipient address.\n * Anyone is allowed to trigger this function since the recipient address cannot be\n * controlled by the msg.sender.\n */\n function withdrawFromTeleportr() external {\n Teleportr(teleportr).withdrawBalance();\n (bool success, ) = recipient.call{ value: address(this).balance }(data);\n require(success, \"TeleportrWithdrawer: send failed\");\n }\n}\n" + }, + "contracts/universal/AssetReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\nimport { Transactor } from \"./Transactor.sol\";\n\n/**\n * @title AssetReceiver\n * @notice AssetReceiver is a minimal contract for receiving funds assets in the form of either\n * ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.\n */\ncontract AssetReceiver is Transactor {\n /**\n * @notice Emitted when ETH is received by this address.\n *\n * @param from Address that sent ETH to this contract.\n * @param amount Amount of ETH received.\n */\n event ReceivedETH(address indexed from, uint256 amount);\n\n /**\n * @notice Emitted when ETH is withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param amount ETH amount withdrawn.\n */\n event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param amount ERC20 amount withdrawn.\n */\n event WithdrewERC20(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 amount\n );\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param id Token ID being withdrawn.\n */\n event WithdrewERC721(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 id\n );\n\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Transactor(_owner) {}\n\n /**\n * @notice Make sure we can receive ETH.\n */\n receive() external payable {\n emit ReceivedETH(msg.sender, msg.value);\n }\n\n /**\n * @notice Withdraws full ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n */\n function withdrawETH(address payable _to) external onlyOwner {\n withdrawETH(_to, address(this).balance);\n }\n\n /**\n * @notice Withdraws partial ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n * @param _amount Amount of ETH to withdraw.\n */\n function withdrawETH(address payable _to, uint256 _amount) public onlyOwner {\n // slither-disable-next-line reentrancy-unlimited-gas\n (bool success, ) = _to.call{ value: _amount }(\"\");\n emit WithdrewETH(msg.sender, _to, _amount);\n }\n\n /**\n * @notice Withdraws full ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n */\n function withdrawERC20(ERC20 _asset, address _to) external onlyOwner {\n withdrawERC20(_asset, _to, _asset.balanceOf(address(this)));\n }\n\n /**\n * @notice Withdraws partial ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n * @param _amount Amount of ERC20 to withdraw.\n */\n function withdrawERC20(\n ERC20 _asset,\n address _to,\n uint256 _amount\n ) public onlyOwner {\n // slither-disable-next-line unchecked-transfer\n _asset.transfer(_to, _amount);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC20(msg.sender, _to, address(_asset), _amount);\n }\n\n /**\n * @notice Withdraws ERC721 token to the recipient.\n *\n * @param _asset ERC721 token to withdraw.\n * @param _to Address to receive the ERC721 token.\n * @param _id Token ID of the ERC721 token to withdraw.\n */\n function withdrawERC721(\n ERC721 _asset,\n address _to,\n uint256 _id\n ) external onlyOwner {\n _asset.transferFrom(address(this), _to, _id);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC721(msg.sender, _to, address(_asset), _id);\n }\n}\n" + }, + "contracts/universal/Transactor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\n\n/**\n * @title Transactor\n * @notice Transactor is a minimal contract that can send transactions.\n */\ncontract Transactor is Owned {\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * Sends a CALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n * @param _value ETH value to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function CALL(\n address _target,\n bytes memory _data,\n uint256 _value\n ) external payable onlyOwner returns (bool, bytes memory) {\n return _target.call{ value: _value }(_data);\n }\n\n /**\n * Sends a DELEGATECALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function DELEGATECALL(address _target, bytes memory _data)\n external\n payable\n onlyOwner\n returns (bool, bytes memory)\n {\n // slither-disable-next-line controlled-delegatecall\n return _target.delegatecall(_data);\n }\n}\n" + }, + "contracts/L2/TeleportrDisburser.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title TeleportrDisburser\n */\ncontract TeleportrDisburser is Ownable {\n /**\n * @notice A struct holding the address and amount to disbursement.\n */\n struct Disbursement {\n uint256 amount;\n address addr;\n }\n\n /**\n * @notice Total number of disbursements processed.\n */\n uint256 public totalDisbursements;\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a disbursement is successfuly sent.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The recipient of the disbursement.\n * @param amount The amount sent to the recipient.\n */\n event DisbursementSuccess(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @notice Emitted any time a disbursement fails to send.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The intended recipient of the disbursement.\n * @param amount The amount intended to be sent to the recipient.\n */\n event DisbursementFailed(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @custom:semver 0.0.1\n */\n constructor() {\n totalDisbursements = 0;\n }\n\n /**\n * @notice Accepts a list of Disbursements and forwards the amount paid to the contract to each\n * recipient. Reverts if there are zero disbursements, the total amount to forward\n * differs from the amount sent in the transaction, or the _nextDepositId is\n * unexpected. Failed disbursements will not cause the method to revert, but will\n * instead be held by the contract and available for the owner to withdraw.\n *\n * @param _nextDepositId The depositId of the first Dispursement.\n * @param _disbursements A list of Disbursements to process.\n */\n function disburse(uint256 _nextDepositId, Disbursement[] calldata _disbursements)\n external\n payable\n onlyOwner\n {\n // Ensure there are disbursements to process.\n uint256 _numDisbursements = _disbursements.length;\n require(_numDisbursements > 0, \"No disbursements\");\n\n // Ensure the _nextDepositId matches our expected value.\n uint256 _depositId = totalDisbursements;\n require(_depositId == _nextDepositId, \"Unexpected next deposit id\");\n unchecked {\n totalDisbursements += _numDisbursements;\n }\n\n // Ensure the amount sent in the transaction is equal to the sum of the\n // disbursements.\n uint256 _totalDisbursed = 0;\n for (uint256 i = 0; i < _numDisbursements; i++) {\n _totalDisbursed += _disbursements[i].amount;\n }\n require(_totalDisbursed == msg.value, \"Disbursement total != amount sent\");\n\n // Process disbursements.\n for (uint256 i = 0; i < _numDisbursements; i++) {\n uint256 _amount = _disbursements[i].amount;\n address _addr = _disbursements[i].addr;\n\n // Deliver the dispursement amount to the receiver. If the\n // disbursement fails, the amount will be kept by the contract\n // rather than reverting to prevent blocking progress on other\n // disbursements.\n\n // slither-disable-next-line calls-loop,reentrancy-events\n (bool success, ) = _addr.call{ value: _amount, gas: 2300 }(\"\");\n if (success) emit DisbursementSuccess(_depositId, _addr, _amount);\n else emit DisbursementFailed(_depositId, _addr, _amount);\n\n unchecked {\n _depositId += 1;\n }\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 balance = address(this).balance;\n emit BalanceWithdrawn(_owner, balance);\n payable(_owner).transfer(balance);\n }\n}\n" + }, + "contracts/L1/TeleportrDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:attribution https://github.com/0xclem/teleportr\n * @title TeleportrDeposit\n * @notice A contract meant to manage deposits into Optimism's Teleportr custodial bridge. Deposits\n * are rate limited to avoid a situation where too much ETH is flowing through this bridge\n * and cannot be properly disbursed on L2. Inspired by 0xclem's original Teleportr system\n * (https://github.com/0xclem/teleportr).\n */\ncontract TeleportrDeposit is Ownable {\n /**\n * @notice Minimum deposit amount (in wei).\n */\n uint256 public minDepositAmount;\n\n /**\n * @notice Maximum deposit amount (in wei).\n */\n uint256 public maxDepositAmount;\n\n /**\n * @notice Maximum balance this contract will hold before it starts rejecting deposits.\n */\n uint256 public maxBalance;\n\n /**\n * @notice Total number of deposits received.\n */\n uint256 public totalDeposits;\n\n /**\n * @notice Emitted any time the minimum deposit amount is set.\n *\n * @param previousAmount The previous minimum deposit amount.\n * @param newAmount The new minimum deposit amount.\n */\n event MinDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the maximum deposit amount is set.\n *\n * @param previousAmount The previous maximum deposit amount.\n * @param newAmount The new maximum deposit amount.\n */\n event MaxDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the contract maximum balance is set.\n *\n * @param previousBalance The previous maximum contract balance.\n * @param newBalance The new maximum contract balance.\n */\n event MaxBalanceSet(uint256 previousBalance, uint256 newBalance);\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a successful deposit is received.\n *\n * @param depositId A unique sequencer number identifying the deposit.\n * @param emitter The sending address of the payer.\n * @param amount The amount deposited by the payer.\n */\n event EtherReceived(uint256 indexed depositId, address indexed emitter, uint256 indexed amount);\n\n /**\n * @custom:semver 0.0.1\n *\n * @param _minDepositAmount The initial minimum deposit amount.\n * @param _maxDepositAmount The initial maximum deposit amount.\n * @param _maxBalance The initial maximum contract balance.\n */\n constructor(\n uint256 _minDepositAmount,\n uint256 _maxDepositAmount,\n uint256 _maxBalance\n ) {\n minDepositAmount = _minDepositAmount;\n maxDepositAmount = _maxDepositAmount;\n maxBalance = _maxBalance;\n totalDeposits = 0;\n emit MinDepositAmountSet(0, _minDepositAmount);\n emit MaxDepositAmountSet(0, _maxDepositAmount);\n emit MaxBalanceSet(0, _maxBalance);\n }\n\n /**\n * @notice Accepts deposits that will be disbursed to the sender's address on L2.\n */\n receive() external payable {\n require(msg.value >= minDepositAmount, \"Deposit amount is too small\");\n require(msg.value <= maxDepositAmount, \"Deposit amount is too big\");\n require(address(this).balance <= maxBalance, \"Contract max balance exceeded\");\n\n emit EtherReceived(totalDeposits, msg.sender, msg.value);\n unchecked {\n totalDeposits += 1;\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 _balance = address(this).balance;\n emit BalanceWithdrawn(_owner, _balance);\n payable(_owner).transfer(_balance);\n }\n\n /**\n * @notice Sets the minimum amount that can be deposited in a receive.\n *\n * @param _minDepositAmount The new minimum deposit amount.\n */\n function setMinAmount(uint256 _minDepositAmount) external onlyOwner {\n emit MinDepositAmountSet(minDepositAmount, _minDepositAmount);\n minDepositAmount = _minDepositAmount;\n }\n\n /**\n * @notice Sets the maximum amount that can be deposited in a receive.\n *\n * @param _maxDepositAmount The new maximum deposit amount.\n */\n function setMaxAmount(uint256 _maxDepositAmount) external onlyOwner {\n emit MaxDepositAmountSet(maxDepositAmount, _maxDepositAmount);\n maxDepositAmount = _maxDepositAmount;\n }\n\n /**\n * @notice Sets the maximum balance the contract can hold after a receive.\n *\n * @param _maxBalance The new maximum contract balance.\n */\n function setMaxBalance(uint256 _maxBalance) external onlyOwner {\n emit MaxBalanceSet(maxBalance, _maxBalance);\n maxBalance = _maxBalance;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism/L2ERC721Bridge.json b/packages/contracts-periphery/deployments/optimism/L2ERC721Bridge.json new file mode 100644 index 0000000000000..fe0939d459193 --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism/L2ERC721Bridge.json @@ -0,0 +1,386 @@ +{ + "address": "0x5a7749f83b81B301cAb5f48EB8516B986DAef23D", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_messenger", + "type": "address" + }, + { + "internalType": "address", + "name": "_otherBridge", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC721BridgeFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC721BridgeInitiated", + "type": "event" + }, + { + "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" + } + ], + "name": "bridgeERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "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" + } + ], + "name": "bridgeERC721To", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "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" + } + ], + "name": "finalizeBridgeERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "messenger", + "outputs": [ + { + "internalType": "contract CrossDomainMessenger", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "otherBridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x4455387bbc834a39d85d9c6d5547960d447932e163ca4f31346751845bde2d2f", + "receipt": { + "to": null, + "from": "0x53A6eecC2dD4795Fcc68940ddc6B4d53Bd88Bd9E", + "contractAddress": "0x5a7749f83b81B301cAb5f48EB8516B986DAef23D", + "transactionIndex": 0, + "gasUsed": "1344187", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x31bd7880fdc5835a924663f5f4f768fc7dde8edebab62d98d6cd9c7385f63430", + "transactionHash": "0x4455387bbc834a39d85d9c6d5547960d447932e163ca4f31346751845bde2d2f", + "logs": [], + "blockNumber": 27392732, + "cumulativeGasUsed": "1344187", + "status": 1, + "byzantium": true + }, + "args": [ + "0x4200000000000000000000000000000000000007", + "0x5a7749f83b81B301cAb5f48EB8516B986DAef23D" + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeInitiated\",\"type\":\"event\"},{\"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\"}],\"name\":\"bridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}],\"name\":\"bridgeERC721To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}],\"name\":\"finalizeBridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"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\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\",\"_otherBridge\":\"Address of the ERC721 bridge on the other network.\"}},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to L1. Data supplied here will not be used to execute any code on L1 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.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"L2ERC721Bridge\",\"version\":1},\"userdoc\":{\"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.\"}},\"kind\":\"user\",\"methods\":{\"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.\"},\"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.\"},\"messenger()\":{\"notice\":\"Messenger contract on this domain.\"},\"otherBridge()\":{\"notice\":\"Address of the bridge on the other network.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge. This contract also acts as a burner for tokens being withdrawn. **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.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/L2ERC721Bridge.sol\":\"L2ERC721Bridge\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { Types } from \\\"./Types.sol\\\";\\nimport { Hashing } from \\\"./Hashing.sol\\\";\\nimport { RLPWriter } from \\\"./rlp/RLPWriter.sol\\\";\\n\\n/**\\n * @title Encoding\\n * @notice Encoding handles Optimism's various different encoding schemes.\\n */\\nlibrary Encoding {\\n /**\\n * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\\n * to the L2 system. Useful for searching for a deposit in the L2 system. The\\n * transaction is prefixed with 0x7e to identify its EIP-2718 type.\\n *\\n * @param _tx User deposit transaction to encode.\\n *\\n * @return RLP encoded L2 deposit transaction.\\n */\\n function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\\n internal\\n pure\\n returns (bytes memory)\\n {\\n bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\\n bytes[] memory raw = new bytes[](8);\\n raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\\n raw[1] = RLPWriter.writeAddress(_tx.from);\\n raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\\\"\\\") : RLPWriter.writeAddress(_tx.to);\\n raw[3] = RLPWriter.writeUint(_tx.mint);\\n raw[4] = RLPWriter.writeUint(_tx.value);\\n raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\\n raw[6] = RLPWriter.writeBool(false);\\n raw[7] = RLPWriter.writeBytes(_tx.data);\\n return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\\n }\\n\\n /**\\n * @notice Encodes the cross domain message based on the version that is encoded into the\\n * message nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes memory) {\\n (, uint16 version) = decodeVersionedNonce(_nonce);\\n if (version == 0) {\\n return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\\n } else if (version == 1) {\\n return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\\n } else {\\n revert(\\\"Encoding: unknown cross domain message version\\\");\\n }\\n }\\n\\n /**\\n * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\\n *\\n * @param _target Address of the target of the message.\\n * @param _sender Address of the sender of the message.\\n * @param _data Data to send with the message.\\n * @param _nonce Message nonce.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessageV0(\\n address _target,\\n address _sender,\\n bytes memory _data,\\n uint256 _nonce\\n ) internal pure returns (bytes memory) {\\n return\\n abi.encodeWithSignature(\\n \\\"relayMessage(address,address,bytes,uint256)\\\",\\n _target,\\n _sender,\\n _data,\\n _nonce\\n );\\n }\\n\\n /**\\n * @notice Encodes a cross domain message based on the V1 (current) encoding.\\n *\\n * @param _nonce Message nonce.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Encoded cross domain message.\\n */\\n function encodeCrossDomainMessageV1(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes memory) {\\n return\\n abi.encodeWithSignature(\\n \\\"relayMessage(uint256,address,address,uint256,uint256,bytes)\\\",\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _gasLimit,\\n _data\\n );\\n }\\n\\n /**\\n * @notice Adds a version number into the first two bytes of a message nonce.\\n *\\n * @param _nonce Message nonce to encode into.\\n * @param _version Version number to encode into the message nonce.\\n *\\n * @return Message nonce with version encoded into the first two bytes.\\n */\\n function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\\n uint256 nonce;\\n assembly {\\n nonce := or(shl(240, _version), _nonce)\\n }\\n return nonce;\\n }\\n\\n /**\\n * @notice Pulls the version out of a version-encoded nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n *\\n * @return Nonce without encoded version.\\n * @return Version of the message.\\n */\\n function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\\n uint240 nonce;\\n uint16 version;\\n assembly {\\n nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\\n version := shr(240, _nonce)\\n }\\n return (nonce, version);\\n }\\n}\\n\",\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { Types } from \\\"./Types.sol\\\";\\nimport { Encoding } from \\\"./Encoding.sol\\\";\\n\\n/**\\n * @title Hashing\\n * @notice Hashing handles Optimism's various different hashing schemes.\\n */\\nlibrary Hashing {\\n /**\\n * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\\n * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\\n * system.\\n *\\n * @param _tx User deposit transaction to hash.\\n *\\n * @return Hash of the RLP encoded L2 deposit transaction.\\n */\\n function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return keccak256(Encoding.encodeDepositTransaction(_tx));\\n }\\n\\n /**\\n * @notice Computes the deposit transaction's \\\"source hash\\\", a value that guarantees the hash\\n * of the L2 transaction that corresponds to a deposit is unique and is\\n * deterministically generated from L1 transaction data.\\n *\\n * @param _l1BlockHash Hash of the L1 block where the deposit was included.\\n * @param _logIndex The index of the log that created the deposit transaction.\\n *\\n * @return Hash of the deposit transaction's \\\"source hash\\\".\\n */\\n function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\\n internal\\n pure\\n returns (bytes32)\\n {\\n bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\\n return keccak256(abi.encode(bytes32(0), depositId));\\n }\\n\\n /**\\n * @notice Hashes the cross domain message based on the version that is encoded into the\\n * message nonce.\\n *\\n * @param _nonce Message nonce with version encoded into the first two bytes.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes32) {\\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\\n if (version == 0) {\\n return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\\n } else if (version == 1) {\\n return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\\n } else {\\n revert(\\\"Hashing: unknown cross domain message version\\\");\\n }\\n }\\n\\n /**\\n * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\\n *\\n * @param _target Address of the target of the message.\\n * @param _sender Address of the sender of the message.\\n * @param _data Data to send with the message.\\n * @param _nonce Message nonce.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessageV0(\\n address _target,\\n address _sender,\\n bytes memory _data,\\n uint256 _nonce\\n ) internal pure returns (bytes32) {\\n return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\\n }\\n\\n /**\\n * @notice Hashes a cross domain message based on the V1 (current) encoding.\\n *\\n * @param _nonce Message nonce.\\n * @param _sender Address of the sender of the message.\\n * @param _target Address of the target of the message.\\n * @param _value ETH value to send to the target.\\n * @param _gasLimit Gas limit to use for the message.\\n * @param _data Data to send with the message.\\n *\\n * @return Hashed cross domain message.\\n */\\n function hashCrossDomainMessageV1(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _gasLimit,\\n bytes memory _data\\n ) internal pure returns (bytes32) {\\n return\\n keccak256(\\n Encoding.encodeCrossDomainMessageV1(\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _gasLimit,\\n _data\\n )\\n );\\n }\\n\\n /**\\n * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\\n *\\n * @param _tx Withdrawal transaction to hash.\\n *\\n * @return Hashed withdrawal transaction.\\n */\\n function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\\n );\\n }\\n\\n /**\\n * @notice Hashes the various elements of an output root proof into an output root hash which\\n * can be used to check if the proof is valid.\\n *\\n * @param _outputRootProof Output root proof which should hash to an output root.\\n *\\n * @return Hashed output root proof.\\n */\\n function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\\n internal\\n pure\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encode(\\n _outputRootProof.version,\\n _outputRootProof.stateRoot,\\n _outputRootProof.messagePasserStorageRoot,\\n _outputRootProof.latestBlockhash\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title SafeCall\\n * @notice Perform low level safe calls\\n */\\nlibrary SafeCall {\\n /**\\n * @notice Perform a low level call without copying any returndata\\n *\\n * @param _target Address to call\\n * @param _gas Amount of gas to pass to the call\\n * @param _value Amount of value to pass to the call\\n * @param _calldata Calldata to pass to the call\\n */\\n function call(\\n address _target,\\n uint256 _gas,\\n uint256 _value,\\n bytes memory _calldata\\n ) internal returns (bool) {\\n bool _success;\\n assembly {\\n _success := call(\\n _gas, // gas\\n _target, // recipient\\n _value, // ether value\\n add(_calldata, 0x20), // inloc\\n mload(_calldata), // inlen\\n 0, // outloc\\n 0 // outlen\\n )\\n }\\n return _success;\\n }\\n}\\n\",\"keccak256\":\"0xbb0621c028c18e9d5a54cf1a8136cf2e77f161de48aeb8d911e230f6b280c9ed\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title Types\\n * @notice Contains various types used throughout the Optimism contract system.\\n */\\nlibrary Types {\\n /**\\n * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\\n * timestamp that the output root is posted. This timestamp is used to verify that the\\n * finalization period has passed since the output root was submitted.\\n */\\n struct OutputProposal {\\n bytes32 outputRoot;\\n uint256 timestamp;\\n }\\n\\n /**\\n * @notice Struct representing the elements that are hashed together to generate an output root\\n * which itself represents a snapshot of the L2 state.\\n */\\n struct OutputRootProof {\\n bytes32 version;\\n bytes32 stateRoot;\\n bytes32 messagePasserStorageRoot;\\n bytes32 latestBlockhash;\\n }\\n\\n /**\\n * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\\n * user (as opposed to a system deposit transaction generated by the system).\\n */\\n struct UserDepositTransaction {\\n address from;\\n address to;\\n bool isCreation;\\n uint256 value;\\n uint256 mint;\\n uint64 gasLimit;\\n bytes data;\\n bytes32 l1BlockHash;\\n uint256 logIndex;\\n }\\n\\n /**\\n * @notice Struct representing a withdrawal transaction.\\n */\\n struct WithdrawalTransaction {\\n uint256 nonce;\\n address sender;\\n address target;\\n uint256 value;\\n uint256 gasLimit;\\n bytes data;\\n }\\n}\\n\",\"keccak256\":\"0x69ca98e57a7cbe60cffeb0f76f6f9279010941b1931581e9a35478f30e2546d1\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\\n * @title RLPWriter\\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\\n * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\\n * modifications to improve legibility.\\n */\\nlibrary RLPWriter {\\n /**\\n * @notice RLP encodes a byte string.\\n *\\n * @param _in The byte string to encode.\\n *\\n * @return The RLP encoded string in bytes.\\n */\\n function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\\n bytes memory encoded;\\n\\n if (_in.length == 1 && uint8(_in[0]) < 128) {\\n encoded = _in;\\n } else {\\n encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\\n }\\n\\n return encoded;\\n }\\n\\n /**\\n * @notice RLP encodes a list of RLP encoded byte byte strings.\\n *\\n * @param _in The list of RLP encoded byte strings.\\n *\\n * @return The RLP encoded list of items in bytes.\\n */\\n function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\\n bytes memory list = _flatten(_in);\\n return abi.encodePacked(_writeLength(list.length, 192), list);\\n }\\n\\n /**\\n * @notice RLP encodes a string.\\n *\\n * @param _in The string to encode.\\n *\\n * @return The RLP encoded string in bytes.\\n */\\n function writeString(string memory _in) internal pure returns (bytes memory) {\\n return writeBytes(bytes(_in));\\n }\\n\\n /**\\n * @notice RLP encodes an address.\\n *\\n * @param _in The address to encode.\\n *\\n * @return The RLP encoded address in bytes.\\n */\\n function writeAddress(address _in) internal pure returns (bytes memory) {\\n return writeBytes(abi.encodePacked(_in));\\n }\\n\\n /**\\n * @notice RLP encodes a uint.\\n *\\n * @param _in The uint256 to encode.\\n *\\n * @return The RLP encoded uint256 in bytes.\\n */\\n function writeUint(uint256 _in) internal pure returns (bytes memory) {\\n return writeBytes(_toBinary(_in));\\n }\\n\\n /**\\n * @notice RLP encodes a bool.\\n *\\n * @param _in The bool to encode.\\n *\\n * @return The RLP encoded bool in bytes.\\n */\\n function writeBool(bool _in) internal pure returns (bytes memory) {\\n bytes memory encoded = new bytes(1);\\n encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\\n return encoded;\\n }\\n\\n /**\\n * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\\n *\\n * @param _len The length of the string or the payload.\\n * @param _offset 128 if item is string, 192 if item is list.\\n *\\n * @return RLP encoded bytes.\\n */\\n function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\\n bytes memory encoded;\\n\\n if (_len < 56) {\\n encoded = new bytes(1);\\n encoded[0] = bytes1(uint8(_len) + uint8(_offset));\\n } else {\\n uint256 lenLen;\\n uint256 i = 1;\\n while (_len / i != 0) {\\n lenLen++;\\n i *= 256;\\n }\\n\\n encoded = new bytes(lenLen + 1);\\n encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\\n for (i = 1; i <= lenLen; i++) {\\n encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\\n }\\n }\\n\\n return encoded;\\n }\\n\\n /**\\n * @notice Encode integer in big endian binary form with no leading zeroes.\\n *\\n * @param _x The integer to encode.\\n *\\n * @return RLP encoded bytes.\\n */\\n function _toBinary(uint256 _x) private pure returns (bytes memory) {\\n bytes memory b = abi.encodePacked(_x);\\n\\n uint256 i = 0;\\n for (; i < 32; i++) {\\n if (b[i] != 0) {\\n break;\\n }\\n }\\n\\n bytes memory res = new bytes(32 - i);\\n for (uint256 j = 0; j < res.length; j++) {\\n res[j] = b[i++];\\n }\\n\\n return res;\\n }\\n\\n /**\\n * @custom:attribution https://github.com/Arachnid/solidity-stringutils\\n * @notice Copies a piece of memory to another location.\\n *\\n * @param _dest Destination location.\\n * @param _src Source location.\\n * @param _len Length of memory to copy.\\n */\\n function _memcpy(\\n uint256 _dest,\\n uint256 _src,\\n uint256 _len\\n ) private pure {\\n uint256 dest = _dest;\\n uint256 src = _src;\\n uint256 len = _len;\\n\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n uint256 mask;\\n unchecked {\\n mask = 256**(32 - len) - 1;\\n }\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n\\n /**\\n * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\\n * @notice Flattens a list of byte strings into one byte string.\\n *\\n * @param _list List of byte strings to flatten.\\n *\\n * @return The flattened byte string.\\n */\\n function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\\n if (_list.length == 0) {\\n return new bytes(0);\\n }\\n\\n uint256 len;\\n uint256 i = 0;\\n for (; i < _list.length; i++) {\\n len += _list[i].length;\\n }\\n\\n bytes memory flattened = new bytes(len);\\n uint256 flattenedPtr;\\n assembly {\\n flattenedPtr := add(flattened, 0x20)\\n }\\n\\n for (i = 0; i < _list.length; i++) {\\n bytes memory item = _list[i];\\n\\n uint256 listPtr;\\n assembly {\\n listPtr := add(item, 0x20)\\n }\\n\\n _memcpy(flattenedPtr, listPtr, item.length);\\n flattenedPtr += _list[i].length;\\n }\\n\\n return flattened;\\n }\\n}\\n\",\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {\\n PausableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {\\n ReentrancyGuardUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeCall } from \\\"../libraries/SafeCall.sol\\\";\\nimport { Hashing } from \\\"../libraries/Hashing.sol\\\";\\nimport { Encoding } from \\\"../libraries/Encoding.sol\\\";\\n\\n/**\\n * @custom:legacy\\n * @title CrossDomainMessengerLegacySpacer\\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\\n * libAddressManager variable used to exist. Must be the first contract in the inheritance\\n * tree of the CrossDomainMessenger\\n */\\ncontract CrossDomainMessengerLegacySpacer {\\n /**\\n * @custom:legacy\\n * @custom:spacer libAddressManager\\n * @notice Spacer for backwards compatibility.\\n */\\n address private spacer_0_0_20;\\n}\\n\\n/**\\n * @custom:upgradeable\\n * @title CrossDomainMessenger\\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\\n * cross-chain messenger contracts. It's designed to be a universal interface that only\\n * needs to be extended slightly to provide low-level message passing functionality on each\\n * chain it's deployed on. Currently only designed for message passing between two paired\\n * chains and does not support one-to-many interactions.\\n */\\nabstract contract CrossDomainMessenger is\\n CrossDomainMessengerLegacySpacer,\\n OwnableUpgradeable,\\n PausableUpgradeable,\\n ReentrancyGuardUpgradeable\\n{\\n /**\\n * @notice Current message version identifier.\\n */\\n uint16 public constant MESSAGE_VERSION = 1;\\n\\n /**\\n * @notice Constant overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\\n\\n /**\\n * @notice Numerator for dynamic overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\\n\\n /**\\n * @notice Denominator for dynamic overhead added to the base gas for a message.\\n */\\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\\n\\n /**\\n * @notice Extra gas added to base gas for each byte of calldata in a message.\\n */\\n uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\\n\\n /**\\n * @notice Minimum amount of gas required to relay a message.\\n */\\n uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\\n\\n /**\\n * @notice Amount of gas held in reserve to guarantee that relay execution completes.\\n */\\n uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\\n\\n /**\\n * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\\n * because performing an SSTORE on a non-zero value is significantly cheaper than on a\\n * zero value.\\n */\\n address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\\n\\n /**\\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\\n */\\n address public immutable otherMessenger;\\n\\n /**\\n * @custom:legacy\\n * @custom:spacer blockedMessages\\n * @notice Spacer for backwards compatibility.\\n */\\n mapping(bytes32 => bool) private spacer_201_0_32;\\n\\n /**\\n * @custom:legacy\\n * @custom:spacer relayedMessages\\n * @notice Spacer for backwards compatibility.\\n */\\n mapping(bytes32 => bool) private spacer_202_0_32;\\n\\n /**\\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\\n * be present in this mapping if it has successfully been relayed on this chain, and\\n * can therefore not be relayed again.\\n */\\n mapping(bytes32 => bool) public successfulMessages;\\n\\n /**\\n * @notice Address of the sender of the currently executing message on the other chain. If the\\n * value of this variable is the default value (0x00000000...dead) then no message is\\n * currently being executed. Use the xDomainMessageSender getter which will throw an\\n * error if this is the case.\\n */\\n address internal xDomainMsgSender;\\n\\n /**\\n * @notice Nonce for the next message to be sent, without the message version applied. Use the\\n * messageNonce getter which will insert the message version into the nonce to give you\\n * the actual nonce to be used for the message.\\n */\\n uint240 internal msgNonce;\\n\\n /**\\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\\n * be present in this mapping if it failed to be relayed on this chain at least once.\\n * If a message is successfully relayed on the first attempt, then it will only be\\n * present within the successfulMessages mapping.\\n */\\n mapping(bytes32 => bool) public receivedMessages;\\n\\n /**\\n * @notice Reserve extra slots in the storage layout for future upgrades.\\n * A gap size of 41 was chosen here, so that the first slot used in a child contract\\n * would be a multiple of 50.\\n */\\n uint256[42] private __gap;\\n\\n /**\\n * @notice Emitted whenever a message is sent to the other chain.\\n *\\n * @param target Address of the recipient of the message.\\n * @param sender Address of the sender of the message.\\n * @param message Message to trigger the recipient address with.\\n * @param messageNonce Unique nonce attached to the message.\\n * @param gasLimit Minimum gas limit that the message can be executed with.\\n */\\n event SentMessage(\\n address indexed target,\\n address sender,\\n bytes message,\\n uint256 messageNonce,\\n uint256 gasLimit\\n );\\n\\n /**\\n * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\\n * SentMessage event without breaking the ABI of this contract, this is good enough.\\n *\\n * @param sender Address of the sender of the message.\\n * @param value ETH value sent along with the message to the recipient.\\n */\\n event SentMessageExtension1(address indexed sender, uint256 value);\\n\\n /**\\n * @notice Emitted whenever a message is successfully relayed on this chain.\\n *\\n * @param msgHash Hash of the message that was relayed.\\n */\\n event RelayedMessage(bytes32 indexed msgHash);\\n\\n /**\\n * @notice Emitted whenever a message fails to be relayed on this chain.\\n *\\n * @param msgHash Hash of the message that failed to be relayed.\\n */\\n event FailedRelayedMessage(bytes32 indexed msgHash);\\n\\n /**\\n * @param _otherMessenger Address of the messenger on the paired chain.\\n */\\n constructor(address _otherMessenger) {\\n otherMessenger = _otherMessenger;\\n }\\n\\n /**\\n * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\\n * security mechanism just in case. Owner should be the same as the upgrade wallet to\\n * maintain the security model of the system as a whole.\\n */\\n function pause() external onlyOwner {\\n _pause();\\n }\\n\\n /**\\n * @notice Allows the owner of this contract to resume message relaying once paused.\\n */\\n function unpause() external onlyOwner {\\n _unpause();\\n }\\n\\n /**\\n * @notice Sends a message to some target address on the other chain. Note that if the call\\n * always reverts, then the message will be unrelayable, and any ETH sent will be\\n * permanently locked. The same will occur if the target on the other chain is\\n * considered unsafe (see the _isUnsafeTarget() function).\\n *\\n * @param _target Target contract or wallet address.\\n * @param _message Message to trigger the target address with.\\n * @param _minGasLimit Minimum gas limit that the message can be executed with.\\n */\\n function sendMessage(\\n address _target,\\n bytes calldata _message,\\n uint32 _minGasLimit\\n ) external payable {\\n // Triggers a message to the other messenger. Note that the amount of gas provided to the\\n // message is the amount of gas requested by the user PLUS the base gas value. We want to\\n // guarantee the property that the call to the target contract will always have at least\\n // the minimum gas limit specified by the user.\\n _sendMessage(\\n otherMessenger,\\n baseGas(_message, _minGasLimit),\\n msg.value,\\n abi.encodeWithSelector(\\n this.relayMessage.selector,\\n messageNonce(),\\n msg.sender,\\n _target,\\n msg.value,\\n _minGasLimit,\\n _message\\n )\\n );\\n\\n emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\\n emit SentMessageExtension1(msg.sender, msg.value);\\n\\n unchecked {\\n ++msgNonce;\\n }\\n }\\n\\n /**\\n * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\\n * be executed via cross-chain call from the other messenger OR if the message was\\n * already received once and is currently being replayed.\\n *\\n * @param _nonce Nonce of the message being relayed.\\n * @param _sender Address of the user who sent the message.\\n * @param _target Address that the message is targeted at.\\n * @param _value ETH value to send with the message.\\n * @param _minGasLimit Minimum amount of gas that the message can be executed with.\\n * @param _message Message to send to the target.\\n */\\n function relayMessage(\\n uint256 _nonce,\\n address _sender,\\n address _target,\\n uint256 _value,\\n uint256 _minGasLimit,\\n bytes calldata _message\\n ) external payable nonReentrant whenNotPaused {\\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\\n\\n // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\\n // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\\n // to the value or minGasLimit fields, which can create unexpected issues for end-users.\\n require(\\n version == 1,\\n \\\"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\\\"\\n );\\n\\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\\n _nonce,\\n _sender,\\n _target,\\n _value,\\n _minGasLimit,\\n _message\\n );\\n\\n if (_isOtherMessenger()) {\\n // This property should always hold when the message is first submitted (as opposed to\\n // being replayed).\\n assert(msg.value == _value);\\n } else {\\n require(\\n msg.value == 0,\\n \\\"CrossDomainMessenger: value must be zero unless message is from a system address\\\"\\n );\\n\\n require(\\n receivedMessages[versionedHash],\\n \\\"CrossDomainMessenger: message cannot be replayed\\\"\\n );\\n }\\n\\n require(\\n _isUnsafeTarget(_target) == false,\\n \\\"CrossDomainMessenger: cannot send message to blocked system address\\\"\\n );\\n\\n require(\\n successfulMessages[versionedHash] == false,\\n \\\"CrossDomainMessenger: message has already been relayed\\\"\\n );\\n\\n require(\\n gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\\n \\\"CrossDomainMessenger: insufficient gas to relay message\\\"\\n );\\n\\n xDomainMsgSender = _sender;\\n bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\\n\\n if (success == true) {\\n successfulMessages[versionedHash] = true;\\n emit RelayedMessage(versionedHash);\\n } else {\\n receivedMessages[versionedHash] = true;\\n emit FailedRelayedMessage(versionedHash);\\n }\\n }\\n\\n /**\\n * @notice Retrieves the address of the contract or wallet that initiated the currently\\n * executing message on the other chain. Will throw an error if there is no message\\n * currently being executed. Allows the recipient of a call to see who triggered it.\\n *\\n * @return Address of the sender of the currently executing message on the other chain.\\n */\\n function xDomainMessageSender() external view returns (address) {\\n require(\\n xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\\n \\\"CrossDomainMessenger: xDomainMessageSender is not set\\\"\\n );\\n\\n return xDomainMsgSender;\\n }\\n\\n /**\\n * @notice Retrieves the next message nonce. Message version will be added to the upper two\\n * bytes of the message nonce. Message version allows us to treat messages as having\\n * different structures.\\n *\\n * @return Nonce of the next message to be sent, with added message version.\\n */\\n function messageNonce() public view returns (uint256) {\\n return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\\n }\\n\\n /**\\n * @notice Computes the amount of gas required to guarantee that a given message will be\\n * received on the other chain without running out of gas. Guaranteeing that a message\\n * will not run out of gas is important because this ensures that a message can always\\n * be replayed on the other chain if it fails to execute completely.\\n *\\n * @param _message Message to compute the amount of required gas for.\\n * @param _minGasLimit Minimum desired gas limit when message goes to target.\\n *\\n * @return Amount of gas required to guarantee message receipt.\\n */\\n function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\\n return\\n // Dynamic overhead\\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\\n // Calldata overhead\\n (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\\n // Constant overhead\\n MIN_GAS_CONSTANT_OVERHEAD;\\n }\\n\\n /**\\n * @notice Intializer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function __CrossDomainMessenger_init() internal onlyInitializing {\\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\\n __Context_init_unchained();\\n __Ownable_init_unchained();\\n __Pausable_init_unchained();\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n /**\\n * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\\n * contracts because the logic for this depends on the network where the messenger is\\n * being deployed.\\n *\\n * @param _to Recipient of the message on the other chain.\\n * @param _gasLimit Minimum gas limit the message can be executed with.\\n * @param _value Amount of ETH to send with the message.\\n * @param _data Message data.\\n */\\n function _sendMessage(\\n address _to,\\n uint64 _gasLimit,\\n uint256 _value,\\n bytes memory _data\\n ) internal virtual;\\n\\n /**\\n * @notice Checks whether the message is coming from the other messenger. Implemented by child\\n * contracts because the logic for this depends on the network where the messenger is\\n * being deployed.\\n *\\n * @return Whether the message is coming from the other messenger.\\n */\\n function _isOtherMessenger() internal view virtual returns (bool);\\n\\n /**\\n * @notice Checks whether a given call target is a system address that could cause the\\n * messenger to peform an unsafe action. This is NOT a mechanism for blocking user\\n * addresses. This is ONLY used to prevent the execution of messages to specific\\n * system addresses that could cause security issues, e.g., having the\\n * CrossDomainMessenger send messages to itself.\\n *\\n * @param _target Address of the contract to check.\\n *\\n * @return Whether or not the address is an unsafe system address.\\n */\\n function _isUnsafeTarget(address _target) internal view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xead7d44e99f3749f1f45e3f70496c27c2d56e532835c13d02b43ee0d8ff1d593\",\"license\":\"MIT\"},\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.15;\\n\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\n\\n/**\\n * @title Semver\\n * @notice Semver is a simple contract for managing contract versions.\\n */\\ncontract Semver {\\n /**\\n * @notice Contract version number (major).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable PATCH_VERSION;\\n\\n /**\\n * @param _major Version number (major).\\n * @param _minor Version number (minor).\\n * @param _patch Version number (patch).\\n */\\n constructor(\\n uint256 _major,\\n uint256 _minor,\\n uint256 _patch\\n ) {\\n MAJOR_VERSION = _major;\\n MINOR_VERSION = _minor;\\n PATCH_VERSION = _patch;\\n }\\n\\n /**\\n * @notice Returns the full semver contract version.\\n *\\n * @return Semver contract version as a string.\\n */\\n function version() public view returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n Strings.toString(MAJOR_VERSION),\\n \\\".\\\",\\n Strings.toString(MINOR_VERSION),\\n \\\".\\\",\\n Strings.toString(PATCH_VERSION)\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x8215e8fbaace5e06fdf0be26cd8ec224847cf03e89bd78dc8ba3ec2cb429d4fe\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\\n * initialization step. This is essential to configure modules that are added through upgrades and that require\\n * initialization.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized < type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x8cc03c5ac17e8a7396e487cda41fc1f1dfdb91db7d528e6da84bee3b6dd7e167\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/L1/L1ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { ERC721Bridge } from \\\"../universal/op-erc721/ERC721Bridge.sol\\\";\\nimport { IERC721 } from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport { L2ERC721Bridge } from \\\"../L2/L2ERC721Bridge.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title L1ERC721Bridge\\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\\n * acts as an escrow for ERC721 tokens deposited into L2.\\n */\\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\\n /**\\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\\n * by ID was deposited for a given L2 token.\\n */\\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(1, 0, 0)\\n ERC721Bridge(_messenger, _otherBridge)\\n {}\\n\\n /*************************\\n * Cross-chain Functions *\\n *************************/\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\\n * execute any code on L2 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyOtherBridge {\\n require(_localToken != address(this), \\\"L1ERC721Bridge: local token cannot be self\\\");\\n\\n // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\\n require(\\n deposits[_localToken][_remoteToken][_tokenId] == true,\\n \\\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\\\"\\n );\\n\\n // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\\n // Bridge.\\n deposits[_localToken][_remoteToken][_tokenId] = false;\\n\\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\\n // withdrawer.\\n IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @inheritdoc ERC721Bridge\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal override {\\n require(_remoteToken != address(0), \\\"ERC721Bridge: remote token cannot be address(0)\\\");\\n\\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\\n bytes memory message = abi.encodeWithSelector(\\n L2ERC721Bridge.finalizeBridgeERC721.selector,\\n _remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Lock token into bridge\\n deposits[_localToken][_remoteToken][_tokenId] = true;\\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\\n\\n // Send calldata into L2\\n messenger.sendMessage(otherBridge, message, _minGasLimit);\\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0x966ae750603761f5636063e4d1441759bd7e140ba933303d31c62220e75c8869\",\"license\":\"MIT\"},\"contracts/L2/L2ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { ERC721Bridge } from \\\"../universal/op-erc721/ERC721Bridge.sol\\\";\\nimport { ERC165Checker } from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\nimport { L1ERC721Bridge } from \\\"../L1/L1ERC721Bridge.sol\\\";\\nimport { IOptimismMintableERC721 } from \\\"../universal/op-erc721/IOptimismMintableERC721.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title L2ERC721Bridge\\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\\n * This contract also acts as a burner for tokens being withdrawn.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n */\\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge)\\n Semver(1, 0, 0)\\n ERC721Bridge(_messenger, _otherBridge)\\n {}\\n\\n /**\\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\\n * recipient on this domain.\\n *\\n * @param _localToken Address of the ERC721 token on this domain.\\n * @param _remoteToken Address of the ERC721 token on the other domain.\\n * @param _from Address that triggered the bridge on the other domain.\\n * @param _to Address to receive the token on this domain.\\n * @param _tokenId ID of the token being deposited.\\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\\n * execute any code on L1 and is only emitted as extra data for the\\n * convenience of off-chain tooling.\\n */\\n function finalizeBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n bytes calldata _extraData\\n ) external onlyOtherBridge {\\n require(_localToken != address(this), \\\"L2ERC721Bridge: local token cannot be self\\\");\\n\\n // Note that supportsInterface makes a callback to the _localToken address which is user\\n // provided.\\n require(\\n ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\\n \\\"L2ERC721Bridge: local token interface is not compliant\\\"\\n );\\n\\n require(\\n _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\\n \\\"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\\\"\\n );\\n\\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\\n // on L2. Note that safeMint makes a callback to the _to address which is user provided.\\n IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n\\n /**\\n * @inheritdoc ERC721Bridge\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal override {\\n require(_remoteToken != address(0), \\\"ERC721Bridge: remote token cannot be address(0)\\\");\\n\\n // Check that the withdrawal is being initiated by the NFT owner\\n require(\\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\\n \\\"Withdrawal is not being initiated by NFT owner\\\"\\n );\\n\\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\\n // slither-disable-next-line reentrancy-events\\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\\n require(\\n remoteToken == _remoteToken,\\n \\\"L2ERC721Bridge: remote token does not match given value\\\"\\n );\\n\\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\\n // usage\\n // slither-disable-next-line reentrancy-events\\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\\n\\n bytes memory message = abi.encodeWithSelector(\\n L1ERC721Bridge.finalizeBridgeERC721.selector,\\n remoteToken,\\n _localToken,\\n _from,\\n _to,\\n _tokenId,\\n _extraData\\n );\\n\\n // Send message to L1 bridge\\n // slither-disable-next-line reentrancy-events\\n messenger.sendMessage(otherBridge, message, _minGasLimit);\\n\\n // slither-disable-next-line reentrancy-events\\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\\n }\\n}\\n\",\"keccak256\":\"0xedcf2403f87c8c72790c053b44ccd762e99f5cdf0f362123288d6893b4c856b5\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/ERC721Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport {\\n CrossDomainMessenger\\n} from \\\"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\n/**\\n * @title ERC721Bridge\\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\\n */\\nabstract contract ERC721Bridge {\\n /**\\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeInitiated(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\\n *\\n * @param localToken Address of the token on this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param from Address that initiated bridging action.\\n * @param to Address to receive the token.\\n * @param tokenId ID of the specific token deposited.\\n * @param extraData Extra data for use on the client-side.\\n */\\n event ERC721BridgeFinalized(\\n address indexed localToken,\\n address indexed remoteToken,\\n address indexed from,\\n address to,\\n uint256 tokenId,\\n bytes extraData\\n );\\n\\n /**\\n * @notice Messenger contract on this domain.\\n */\\n CrossDomainMessenger public immutable messenger;\\n\\n /**\\n * @notice Address of the bridge on the other network.\\n */\\n address public immutable otherBridge;\\n\\n /**\\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\\n */\\n uint256[49] private __gap;\\n\\n /**\\n * @notice Ensures that the caller is a cross-chain message from the other bridge.\\n */\\n modifier onlyOtherBridge() {\\n require(\\n msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\\n \\\"ERC721Bridge: function can only be called from the other bridge\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on this network.\\n * @param _otherBridge Address of the ERC721 bridge on the other network.\\n */\\n constructor(address _messenger, address _otherBridge) {\\n require(_messenger != address(0), \\\"ERC721Bridge: messenger cannot be address(0)\\\");\\n require(_otherBridge != address(0), \\\"ERC721Bridge: other bridge cannot be address(0)\\\");\\n\\n messenger = CrossDomainMessenger(_messenger);\\n otherBridge = _otherBridge;\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\\n * this function can only be called by EOAs. Smart contract wallets should use the\\n * `bridgeERC721To` function after ensuring that the recipient address on the remote\\n * chain exists. Also note that the current owner of the token on this chain must\\n * approve this contract to operate the NFT before it can be bridged.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\\n * be used to execute any code on the other chain and is only emitted as\\n * extra data for the convenience of off-chain tooling.\\n */\\n function bridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n // Modifier requiring sender to be EOA. This prevents against a user error that would occur\\n // if the sender is a smart contract wallet that has a different address on the remote chain\\n // (or doesn't have an address on the remote chain at all). The user would fail to receive\\n // the NFT if they use this function because it sends the NFT to the same address as the\\n // caller. This check could be bypassed by a malicious contract via initcode, but it takes\\n // care of the user error we want to avoid.\\n require(!Address.isContract(msg.sender), \\\"ERC721Bridge: account is not externally owned\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n msg.sender,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\\n * that the current owner of the token on this chain must approve this contract to\\n * operate the NFT before it can be bridged.\\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\\n * can be refunded on L2.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\\n * be used to execute any code on the other chain and is only emitted as\\n * extra data for the convenience of off-chain tooling.\\n */\\n function bridgeERC721To(\\n address _localToken,\\n address _remoteToken,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) external {\\n require(_to != address(0), \\\"ERC721Bridge: nft recipient cannot be address(0)\\\");\\n\\n _initiateBridgeERC721(\\n _localToken,\\n _remoteToken,\\n msg.sender,\\n _to,\\n _tokenId,\\n _minGasLimit,\\n _extraData\\n );\\n }\\n\\n /**\\n * @notice Internal function for initiating a token bridge to the other domain.\\n *\\n * @param _localToken Address of the ERC721 on this domain.\\n * @param _remoteToken Address of the ERC721 on the remote domain.\\n * @param _from Address of the sender on this domain.\\n * @param _to Address to receive the token on the other domain.\\n * @param _tokenId Token ID to bridge.\\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\\n * @param _extraData Optional data to forward to the other domain. Data supplied here will\\n * not be used to execute any code on the other domain and is only emitted\\n * as extra data for the convenience of off-chain tooling.\\n */\\n function _initiateBridgeERC721(\\n address _localToken,\\n address _remoteToken,\\n address _from,\\n address _to,\\n uint256 _tokenId,\\n uint32 _minGasLimit,\\n bytes calldata _extraData\\n ) internal virtual;\\n}\\n\",\"keccak256\":\"0x24898e2e75865a4e35cde2d62518cb4c15a30b7cdae8a1a37624a82ae2a26eb7\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/IOptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {\\n IERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\\\";\\n\\n/**\\n * @title IOptimismMintableERC721\\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\\n */\\ninterface IOptimismMintableERC721 is IERC721Enumerable {\\n /**\\n * @notice Emitted when a token is minted.\\n *\\n * @param account Address of the account the token was minted to.\\n * @param tokenId Token ID of the minted token.\\n */\\n event Mint(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Emitted when a token is burned.\\n *\\n * @param account Address of the account the token was burned from.\\n * @param tokenId Token ID of the burned token.\\n */\\n event Burn(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Chain ID of the chain where the remote token is deployed.\\n */\\n function remoteChainId() external view returns (uint256);\\n\\n /**\\n * @notice Address of the token on the remote domain.\\n */\\n function remoteToken() external view returns (address);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n function bridge() external view returns (address);\\n\\n /**\\n * @notice Mints some token ID for a user, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * @param _to Address of the user to mint the token for.\\n * @param _tokenId Token ID to mint.\\n */\\n function safeMint(address _to, uint256 _tokenId) external;\\n\\n /**\\n * @notice Burns a token ID from a user.\\n *\\n * @param _from Address of the user to burn the token from.\\n * @param _tokenId Token ID to burn.\\n */\\n function burn(address _from, uint256 _tokenId) external;\\n}\\n\",\"keccak256\":\"0xc3703030d0093d65839b02296e3152681fa1c8d717e66ab3f5a7c32ba3fd0a54\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6101206040523480156200001257600080fd5b506040516200197238038062001972833981016040819052620000359162000162565b600160008084846001600160a01b038216620000ad5760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b0381166200011d5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401620000a4565b6001600160a01b039182166080521660a05260c09290925260e05261010052506200019a9050565b80516001600160a01b03811681146200015d57600080fd5b919050565b600080604083850312156200017657600080fd5b620001818362000145565b9150620001916020840162000145565b90509250929050565b60805160a05160c05160e051610100516117716200020160003960006102440152600061021b015260006101f201526000818161011d015281816102d00152610d630152600081816091015281816102a6015281816103070152610d3601526117716000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063761f449311610050578063761f4493146100f2578063aa55745214610105578063c89701a21461011857600080fd5b80633687011a146100775780633cb747bf1461008c57806354fd4d50146100dd575b600080fd5b61008a6100853660046111d8565b61013f565b005b6100b37f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100e56101eb565b6040516100d491906112d5565b61008a6101003660046112e8565b61028e565b61008a610113366004611380565b6107f5565b6100b37f000000000000000000000000000000000000000000000000000000000000000081565b333b156101d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6101e386863333888888886108b1565b505050505050565b60606102167f0000000000000000000000000000000000000000000000000000000000000000610e4f565b61023f7f0000000000000000000000000000000000000000000000000000000000000000610e4f565b6102687f0000000000000000000000000000000000000000000000000000000000000000610e4f565b60405160200161027a939291906113f7565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103ac57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610370573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610394919061146d565b73ffffffffffffffffffffffffffffffffffffffff16145b610438576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016101ca565b3073ffffffffffffffffffffffffffffffffffffffff8816036104dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016101ca565b610507877fe49bc7f800000000000000000000000000000000000000000000000000000000610f8c565b610593576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e20696e746560448201527f7266616365206973206e6f7420636f6d706c69616e740000000000000000000060648201526084016101ca565b8673ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610602919061146d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146106e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324552433732314272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433732312060648201527f6c6f63616c20746f6b656e000000000000000000000000000000000000000000608482015260a4016101ca565b6040517fa144819400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063a144819490604401600060405180830381600087803b15801561075257600080fd5b505af1158015610766573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107e494939291906114da565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610898576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016101ca565b6108a887873388888888886108b1565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff8716610954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4552433732314272696467653a2072656d6f746520746f6b656e2063616e6e6f60448201527f742062652061646472657373283029000000000000000000000000000000000060648201526084016101ca565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e90602401602060405180830381865afa1580156109bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e3919061146d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f5769746864726177616c206973206e6f74206265696e6720696e69746961746560448201527f64206279204e4654206f776e657200000000000000000000000000000000000060648201526084016101ca565b60008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610aea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0e919061146d565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c756500000000000000000060648201526084016101ca565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790528a1690639dc29fac90604401600060405180830381600087803b158015610c3b57600080fd5b505af1158015610c4f573d6000803e3d6000fd5b50505050600063761f449360e01b828b8a8a8a8989604051602401610c7a9796959493929190611510565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f3dbb202b00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633dbb202b90610d8f907f00000000000000000000000000000000000000000000000000000000000000009085908a9060040161156d565b600060405180830381600087803b158015610da957600080fd5b505af1158015610dbd573d6000803e3d6000fd5b505050508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610e3b94939291906114da565b60405180910390a450505050505050505050565b606081600003610e9257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610ebc5780610ea6816115e1565b9150610eb59050600a83611648565b9150610e96565b60008167ffffffffffffffff811115610ed757610ed761165c565b6040519080825280601f01601f191660200182016040528015610f01576020820181803683370190505b5090505b8415610f8457610f1660018361168b565b9150610f23600a866116a2565b610f2e9060306116b6565b60f81b818381518110610f4357610f436116ce565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610f7d600a86611648565b9450610f05565b949350505050565b6000610f9783610fb1565b8015610fa85750610fa88383611015565b90505b92915050565b6000610fdd827f01ffc9a700000000000000000000000000000000000000000000000000000000611015565b8015610fab575061100e827fffffffff00000000000000000000000000000000000000000000000000000000611015565b1592915050565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a7000000000000000000000000000000000000000000000000000000001790529051600091908290819073ffffffffffffffffffffffffffffffffffffffff871690617530906110cf9086906116fd565b6000604051808303818686fa925050503d806000811461110b576040519150601f19603f3d011682016040523d82523d6000602084013e611110565b606091505b509150915060208151101561112b5760009350505050610fab565b8180156111475750808060200190518101906111479190611719565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461117357600080fd5b50565b803563ffffffff8116811461118a57600080fd5b919050565b60008083601f8401126111a157600080fd5b50813567ffffffffffffffff8111156111b957600080fd5b6020830191508360208285010111156111d157600080fd5b9250929050565b60008060008060008060a087890312156111f157600080fd5b86356111fc81611151565b9550602087013561120c81611151565b94506040870135935061122160608801611176565b9250608087013567ffffffffffffffff81111561123d57600080fd5b61124989828a0161118f565b979a9699509497509295939492505050565b60005b8381101561127657818101518382015260200161125e565b83811115611285576000848401525b50505050565b600081518084526112a381602086016020860161125b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610fa8602083018461128b565b600080600080600080600060c0888a03121561130357600080fd5b873561130e81611151565b9650602088013561131e81611151565b9550604088013561132e81611151565b9450606088013561133e81611151565b93506080880135925060a088013567ffffffffffffffff81111561136157600080fd5b61136d8a828b0161118f565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561139b57600080fd5b87356113a681611151565b965060208801356113b681611151565b955060408801356113c681611151565b9450606088013593506113db60808901611176565b925060a088013567ffffffffffffffff81111561136157600080fd5b6000845161140981846020890161125b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611445816001850160208a0161125b565b6001920191820152835161146081600284016020880161125b565b0160020195945050505050565b60006020828403121561147f57600080fd5b815161148a81611151565b9392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611147606083018486611491565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261156060c083018486611491565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061159c606083018561128b565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611612576116126115b2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165757611657611619565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008282101561169d5761169d6115b2565b500390565b6000826116b1576116b1611619565b500690565b600082198211156116c9576116c96115b2565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825161170f81846020870161125b565b9190910192915050565b60006020828403121561172b57600080fd5b8151801515811461148a57600080fdfea264697066735822122038ebf17853e671ca85694dc6b63a39fe1ec7d19a5f56e16bf6790e2e0b0569e764736f6c634300080f0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063761f449311610050578063761f4493146100f2578063aa55745214610105578063c89701a21461011857600080fd5b80633687011a146100775780633cb747bf1461008c57806354fd4d50146100dd575b600080fd5b61008a6100853660046111d8565b61013f565b005b6100b37f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100e56101eb565b6040516100d491906112d5565b61008a6101003660046112e8565b61028e565b61008a610113366004611380565b6107f5565b6100b37f000000000000000000000000000000000000000000000000000000000000000081565b333b156101d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6101e386863333888888886108b1565b505050505050565b60606102167f0000000000000000000000000000000000000000000000000000000000000000610e4f565b61023f7f0000000000000000000000000000000000000000000000000000000000000000610e4f565b6102687f0000000000000000000000000000000000000000000000000000000000000000610e4f565b60405160200161027a939291906113f7565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103ac57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610370573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610394919061146d565b73ffffffffffffffffffffffffffffffffffffffff16145b610438576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016101ca565b3073ffffffffffffffffffffffffffffffffffffffff8816036104dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016101ca565b610507877fe49bc7f800000000000000000000000000000000000000000000000000000000610f8c565b610593576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e20696e746560448201527f7266616365206973206e6f7420636f6d706c69616e740000000000000000000060648201526084016101ca565b8673ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610602919061146d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146106e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324552433732314272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433732312060648201527f6c6f63616c20746f6b656e000000000000000000000000000000000000000000608482015260a4016101ca565b6040517fa144819400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063a144819490604401600060405180830381600087803b15801561075257600080fd5b505af1158015610766573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107e494939291906114da565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610898576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016101ca565b6108a887873388888888886108b1565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff8716610954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4552433732314272696467653a2072656d6f746520746f6b656e2063616e6e6f60448201527f742062652061646472657373283029000000000000000000000000000000000060648201526084016101ca565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e90602401602060405180830381865afa1580156109bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e3919061146d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f5769746864726177616c206973206e6f74206265696e6720696e69746961746560448201527f64206279204e4654206f776e657200000000000000000000000000000000000060648201526084016101ca565b60008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610aea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0e919061146d565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c756500000000000000000060648201526084016101ca565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790528a1690639dc29fac90604401600060405180830381600087803b158015610c3b57600080fd5b505af1158015610c4f573d6000803e3d6000fd5b50505050600063761f449360e01b828b8a8a8a8989604051602401610c7a9796959493929190611510565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f3dbb202b00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633dbb202b90610d8f907f00000000000000000000000000000000000000000000000000000000000000009085908a9060040161156d565b600060405180830381600087803b158015610da957600080fd5b505af1158015610dbd573d6000803e3d6000fd5b505050508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610e3b94939291906114da565b60405180910390a450505050505050505050565b606081600003610e9257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610ebc5780610ea6816115e1565b9150610eb59050600a83611648565b9150610e96565b60008167ffffffffffffffff811115610ed757610ed761165c565b6040519080825280601f01601f191660200182016040528015610f01576020820181803683370190505b5090505b8415610f8457610f1660018361168b565b9150610f23600a866116a2565b610f2e9060306116b6565b60f81b818381518110610f4357610f436116ce565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610f7d600a86611648565b9450610f05565b949350505050565b6000610f9783610fb1565b8015610fa85750610fa88383611015565b90505b92915050565b6000610fdd827f01ffc9a700000000000000000000000000000000000000000000000000000000611015565b8015610fab575061100e827fffffffff00000000000000000000000000000000000000000000000000000000611015565b1592915050565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a7000000000000000000000000000000000000000000000000000000001790529051600091908290819073ffffffffffffffffffffffffffffffffffffffff871690617530906110cf9086906116fd565b6000604051808303818686fa925050503d806000811461110b576040519150601f19603f3d011682016040523d82523d6000602084013e611110565b606091505b509150915060208151101561112b5760009350505050610fab565b8180156111475750808060200190518101906111479190611719565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461117357600080fd5b50565b803563ffffffff8116811461118a57600080fd5b919050565b60008083601f8401126111a157600080fd5b50813567ffffffffffffffff8111156111b957600080fd5b6020830191508360208285010111156111d157600080fd5b9250929050565b60008060008060008060a087890312156111f157600080fd5b86356111fc81611151565b9550602087013561120c81611151565b94506040870135935061122160608801611176565b9250608087013567ffffffffffffffff81111561123d57600080fd5b61124989828a0161118f565b979a9699509497509295939492505050565b60005b8381101561127657818101518382015260200161125e565b83811115611285576000848401525b50505050565b600081518084526112a381602086016020860161125b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610fa8602083018461128b565b600080600080600080600060c0888a03121561130357600080fd5b873561130e81611151565b9650602088013561131e81611151565b9550604088013561132e81611151565b9450606088013561133e81611151565b93506080880135925060a088013567ffffffffffffffff81111561136157600080fd5b61136d8a828b0161118f565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561139b57600080fd5b87356113a681611151565b965060208801356113b681611151565b955060408801356113c681611151565b9450606088013593506113db60808901611176565b925060a088013567ffffffffffffffff81111561136157600080fd5b6000845161140981846020890161125b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611445816001850160208a0161125b565b6001920191820152835161146081600284016020880161125b565b0160020195945050505050565b60006020828403121561147f57600080fd5b815161148a81611151565b9392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611147606083018486611491565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261156060c083018486611491565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061159c606083018561128b565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611612576116126115b2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165757611657611619565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008282101561169d5761169d6115b2565b500390565b6000826116b1576116b1611619565b500690565b600082198211156116c9576116c96115b2565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825161170f81846020870161125b565b9190910192915050565b60006020828403121561172b57600080fd5b8151801515811461148a57600080fdfea264697066735822122038ebf17853e671ca85694dc6b63a39fe1ec7d19a5f56e16bf6790e2e0b0569e764736f6c634300080f0033", + "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": { + "custom:semver": "1.0.0", + "params": { + "_messenger": "Address of the CrossDomainMessenger on this network.", + "_otherBridge": "Address of the ERC721 bridge on the other network." + } + }, + "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { + "params": { + "_extraData": "Optional data to forward to L1. Data supplied here will not be used to execute any code on L1 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." + } + }, + "version()": { + "returns": { + "_0": "Semver contract version as a string." + } + } + }, + "title": "L2ERC721Bridge", + "version": 1 + }, + "userdoc": { + "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." + } + }, + "kind": "user", + "methods": { + "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." + }, + "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." + }, + "messenger()": { + "notice": "Messenger contract on this domain." + }, + "otherBridge()": { + "notice": "Address of the bridge on the other network." + }, + "version()": { + "notice": "Returns the full semver contract version." + } + }, + "notice": "The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge. This contract also acts as a burner for tokens being withdrawn. **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.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 8088, + "contract": "contracts/L2/L2ERC721Bridge.sol:L2ERC721Bridge", + "label": "__gap", + "offset": 0, + "slot": "0", + "type": "t_array(t_uint256)49_storage" + } + ], + "types": { + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism/OptimismMintableERC721Factory.json b/packages/contracts-periphery/deployments/optimism/OptimismMintableERC721Factory.json new file mode 100644 index 0000000000000..0052dac91020a --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism/OptimismMintableERC721Factory.json @@ -0,0 +1,250 @@ +{ + "address": "0x69D67c1caa8D0717DffA6d2e5B1f7F19926e5EF0", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bridge", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_remoteChainId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "deployer", + "type": "address" + } + ], + "name": "OptimismMintableERC721Created", + "type": "event" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_remoteToken", + "type": "address" + }, + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + } + ], + "name": "createOptimismMintableERC721", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isOptimismMintableERC721", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "remoteChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xffa94dd9f5a43e9dd4c20f1f9335e6a392fcd6066fa70738808432d926b31a68", + "receipt": { + "to": null, + "from": "0x53A6eecC2dD4795Fcc68940ddc6B4d53Bd88Bd9E", + "contractAddress": "0x69D67c1caa8D0717DffA6d2e5B1f7F19926e5EF0", + "transactionIndex": 0, + "gasUsed": "3124569", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xcd388f3b7f032bd0ef8b65aab748193683f5ae671a627a4eee81707bb980bc2a", + "transactionHash": "0xffa94dd9f5a43e9dd4c20f1f9335e6a392fcd6066fa70738808432d926b31a68", + "logs": [], + "blockNumber": 27396228, + "cumulativeGasUsed": "3124569", + "status": 1, + "byzantium": true + }, + "args": [ + "0x4200000000000000000000000000000000000014", + 1 + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_remoteChainId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\"}],\"name\":\"OptimismMintableERC721Created\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createOptimismMintableERC721\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isOptimismMintableERC721\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"remoteChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"OptimismMintableERC721Created(address,address,address)\":{\"params\":{\"deployer\":\"Address of the initiator of the deployment\",\"localToken\":\"Address of the token on the this domain.\",\"remoteToken\":\"Address of the token on the remote domain.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_bridge\":\"Address of the ERC721 bridge on this network.\"}},\"createOptimismMintableERC721(address,string,string)\":{\"params\":{\"_name\":\"ERC721 name.\",\"_remoteToken\":\"Address of the corresponding token on the other domain.\",\"_symbol\":\"ERC721 symbol.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"OptimismMintableERC721Factory\",\"version\":1},\"userdoc\":{\"events\":{\"OptimismMintableERC721Created(address,address,address)\":{\"notice\":\"Emitted whenever a new OptimismMintableERC721 contract is created.\"}},\"kind\":\"user\",\"methods\":{\"bridge()\":{\"notice\":\"Address of the ERC721 bridge on this network.\"},\"createOptimismMintableERC721(address,string,string)\":{\"notice\":\"Creates an instance of the standard ERC721.\"},\"isOptimismMintableERC721(address)\":{\"notice\":\"Tracks addresses created by this factory.\"},\"remoteChainId()\":{\"notice\":\"Chain ID for the remote network.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"Factory contract for creating OptimismMintableERC721 contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-erc721/OptimismMintableERC721Factory.sol\":\"OptimismMintableERC721Factory\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.15;\\n\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\n\\n/**\\n * @title Semver\\n * @notice Semver is a simple contract for managing contract versions.\\n */\\ncontract Semver {\\n /**\\n * @notice Contract version number (major).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n uint256 private immutable PATCH_VERSION;\\n\\n /**\\n * @param _major Version number (major).\\n * @param _minor Version number (minor).\\n * @param _patch Version number (patch).\\n */\\n constructor(\\n uint256 _major,\\n uint256 _minor,\\n uint256 _patch\\n ) {\\n MAJOR_VERSION = _major;\\n MINOR_VERSION = _minor;\\n PATCH_VERSION = _patch;\\n }\\n\\n /**\\n * @notice Returns the full semver contract version.\\n *\\n * @return Semver contract version as a string.\\n */\\n function version() public view returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n Strings.toString(MAJOR_VERSION),\\n \\\".\\\",\\n Strings.toString(MINOR_VERSION),\\n \\\".\\\",\\n Strings.toString(PATCH_VERSION)\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x8215e8fbaace5e06fdf0be26cd8ec224847cf03e89bd78dc8ba3ec2cb429d4fe\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _owners[tokenId];\\n require(owner != address(0), \\\"ERC721: owner query for nonexistent token\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overridden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n _safeTransfer(from, to, tokenId, _data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _owners[tokenId] != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, _data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId);\\n\\n _balances[to] += 1;\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n\\n _afterTokenTransfer(address(0), to, tokenId);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n // Clear approvals\\n _approve(address(0), tokenId);\\n\\n _balances[owner] -= 1;\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n\\n _afterTokenTransfer(owner, address(0), tokenId);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId);\\n\\n // Clear approvals from the previous owner\\n _approve(address(0), tokenId);\\n\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n\\n _afterTokenTransfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits a {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits a {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(\\n address owner,\\n address operator,\\n bool approved\\n ) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param _data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n * transferred to `to`.\\n * - When `from` is zero, `tokenId` will be minted for `to`.\\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x921f012325281f7d81e29c53a13824cf6c2c5d77232065d0d4f3f912e97af6ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC721.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\n\\n/**\\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\\n * enumerability of all the token ids in the contract as well as all token ids owned by each\\n * account.\\n */\\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\\n // Mapping from owner to list of owned token IDs\\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\\n\\n // Mapping from token ID to index of the owner tokens list\\n mapping(uint256 => uint256) private _ownedTokensIndex;\\n\\n // Array with all token ids, used for enumeration\\n uint256[] private _allTokens;\\n\\n // Mapping from token id to position in the allTokens array\\n mapping(uint256 => uint256) private _allTokensIndex;\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n require(index < ERC721.balanceOf(owner), \\\"ERC721Enumerable: owner index out of bounds\\\");\\n return _ownedTokens[owner][index];\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _allTokens.length;\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-tokenByIndex}.\\n */\\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n require(index < ERC721Enumerable.totalSupply(), \\\"ERC721Enumerable: global index out of bounds\\\");\\n return _allTokens[index];\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n * transferred to `to`.\\n * - When `from` is zero, `tokenId` will be minted for `to`.\\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual override {\\n super._beforeTokenTransfer(from, to, tokenId);\\n\\n if (from == address(0)) {\\n _addTokenToAllTokensEnumeration(tokenId);\\n } else if (from != to) {\\n _removeTokenFromOwnerEnumeration(from, tokenId);\\n }\\n if (to == address(0)) {\\n _removeTokenFromAllTokensEnumeration(tokenId);\\n } else if (to != from) {\\n _addTokenToOwnerEnumeration(to, tokenId);\\n }\\n }\\n\\n /**\\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\\n * @param to address representing the new owner of the given token ID\\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\\n */\\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\\n uint256 length = ERC721.balanceOf(to);\\n _ownedTokens[to][length] = tokenId;\\n _ownedTokensIndex[tokenId] = length;\\n }\\n\\n /**\\n * @dev Private function to add a token to this extension's token tracking data structures.\\n * @param tokenId uint256 ID of the token to be added to the tokens list\\n */\\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\\n _allTokensIndex[tokenId] = _allTokens.length;\\n _allTokens.push(tokenId);\\n }\\n\\n /**\\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\\n * @param from address representing the previous owner of the given token ID\\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\\n */\\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\\n // then delete the last slot (swap and pop).\\n\\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\\n\\n // When the token to delete is the last token, the swap operation is unnecessary\\n if (tokenIndex != lastTokenIndex) {\\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\\n\\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\\n }\\n\\n // This also deletes the contents at the last position of the array\\n delete _ownedTokensIndex[tokenId];\\n delete _ownedTokens[from][lastTokenIndex];\\n }\\n\\n /**\\n * @dev Private function to remove a token from this extension's token tracking data structures.\\n * This has O(1) time complexity, but alters the order of the _allTokens array.\\n * @param tokenId uint256 ID of the token to be removed from the tokens list\\n */\\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\\n // then delete the last slot (swap and pop).\\n\\n uint256 lastTokenIndex = _allTokens.length - 1;\\n uint256 tokenIndex = _allTokensIndex[tokenId];\\n\\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\\n uint256 lastTokenId = _allTokens[lastTokenIndex];\\n\\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\\n\\n // This also deletes the contents at the last position of the array\\n delete _allTokensIndex[tokenId];\\n _allTokens.pop();\\n }\\n}\\n\",\"keccak256\":\"0x0a79511df8151b10b0a0004d6a76ad956582d32824af4c0f4886bdbdfe5746e5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/IOptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {\\n IERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\\\";\\n\\n/**\\n * @title IOptimismMintableERC721\\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\\n */\\ninterface IOptimismMintableERC721 is IERC721Enumerable {\\n /**\\n * @notice Emitted when a token is minted.\\n *\\n * @param account Address of the account the token was minted to.\\n * @param tokenId Token ID of the minted token.\\n */\\n event Mint(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Emitted when a token is burned.\\n *\\n * @param account Address of the account the token was burned from.\\n * @param tokenId Token ID of the burned token.\\n */\\n event Burn(address indexed account, uint256 tokenId);\\n\\n /**\\n * @notice Chain ID of the chain where the remote token is deployed.\\n */\\n function remoteChainId() external view returns (uint256);\\n\\n /**\\n * @notice Address of the token on the remote domain.\\n */\\n function remoteToken() external view returns (address);\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n function bridge() external view returns (address);\\n\\n /**\\n * @notice Mints some token ID for a user, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * @param _to Address of the user to mint the token for.\\n * @param _tokenId Token ID to mint.\\n */\\n function safeMint(address _to, uint256 _tokenId) external;\\n\\n /**\\n * @notice Burns a token ID from a user.\\n *\\n * @param _from Address of the user to burn the token from.\\n * @param _tokenId Token ID to burn.\\n */\\n function burn(address _from, uint256 _tokenId) external;\\n}\\n\",\"keccak256\":\"0xc3703030d0093d65839b02296e3152681fa1c8d717e66ab3f5a7c32ba3fd0a54\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/OptimismMintableERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {\\n ERC721Enumerable\\n} from \\\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\\\";\\nimport { ERC721 } from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport { IERC165 } from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport { IOptimismMintableERC721 } from \\\"./IOptimismMintableERC721.sol\\\";\\n\\n/**\\n * @title OptimismMintableERC721\\n * @notice This contract is the remote representation for some token that lives on another network,\\n * typically an Optimism representation of an Ethereum-based token. Standard reference\\n * implementation that can be extended or modified according to your needs.\\n */\\ncontract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n uint256 public immutable remoteChainId;\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n address public immutable remoteToken;\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n address public immutable bridge;\\n\\n /**\\n * @notice Base token URI for this token.\\n */\\n string public baseTokenURI;\\n\\n /**\\n * @param _bridge Address of the bridge on this network.\\n * @param _remoteChainId Chain ID where the remote token is deployed.\\n * @param _remoteToken Address of the corresponding token on the other network.\\n * @param _name ERC721 name.\\n * @param _symbol ERC721 symbol.\\n */\\n constructor(\\n address _bridge,\\n uint256 _remoteChainId,\\n address _remoteToken,\\n string memory _name,\\n string memory _symbol\\n ) ERC721(_name, _symbol) {\\n require(_bridge != address(0), \\\"OptimismMintableERC721: bridge cannot be address(0)\\\");\\n require(_remoteChainId != 0, \\\"OptimismMintableERC721: remote chain id cannot be zero\\\");\\n require(\\n _remoteToken != address(0),\\n \\\"OptimismMintableERC721: remote token cannot be address(0)\\\"\\n );\\n\\n remoteChainId = _remoteChainId;\\n remoteToken = _remoteToken;\\n bridge = _bridge;\\n\\n // Creates a base URI in the format specified by EIP-681:\\n // https://eips.ethereum.org/EIPS/eip-681\\n baseTokenURI = string(\\n abi.encodePacked(\\n \\\"ethereum:\\\",\\n Strings.toHexString(uint160(_remoteToken), 20),\\n \\\"@\\\",\\n Strings.toString(_remoteChainId),\\n \\\"/tokenURI?uint256=\\\"\\n )\\n );\\n }\\n\\n /**\\n * @notice Modifier that prevents callers other than the bridge from calling the function.\\n */\\n modifier onlyBridge() {\\n require(msg.sender == bridge, \\\"OptimismMintableERC721: only bridge can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {\\n _safeMint(_to, _tokenId);\\n\\n emit Mint(_to, _tokenId);\\n }\\n\\n /**\\n * @inheritdoc IOptimismMintableERC721\\n */\\n function burn(address _from, uint256 _tokenId) external virtual onlyBridge {\\n _burn(_tokenId);\\n\\n emit Burn(_from, _tokenId);\\n }\\n\\n /**\\n * @notice Checks if a given interface ID is supported by this contract.\\n *\\n * @param _interfaceId The interface ID to check.\\n *\\n * @return True if the interface ID is supported, false otherwise.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n override(ERC721Enumerable, IERC165)\\n returns (bool)\\n {\\n bytes4 iface1 = type(IERC165).interfaceId;\\n bytes4 iface2 = type(IOptimismMintableERC721).interfaceId;\\n return\\n _interfaceId == iface1 ||\\n _interfaceId == iface2 ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n /**\\n * @notice Returns the base token URI.\\n *\\n * @return Base token URI.\\n */\\n function _baseURI() internal view virtual override returns (string memory) {\\n return baseTokenURI;\\n }\\n}\\n\",\"keccak256\":\"0x5ab0e15ecf5617db181396e9c95087fb403e3276527b6426ae3845ec50514d36\",\"license\":\"MIT\"},\"contracts/universal/op-erc721/OptimismMintableERC721Factory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { OptimismMintableERC721 } from \\\"./OptimismMintableERC721.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title OptimismMintableERC721Factory\\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\\n */\\ncontract OptimismMintableERC721Factory is Semver {\\n /**\\n * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\\n *\\n * @param localToken Address of the token on the this domain.\\n * @param remoteToken Address of the token on the remote domain.\\n * @param deployer Address of the initiator of the deployment\\n */\\n event OptimismMintableERC721Created(\\n address indexed localToken,\\n address indexed remoteToken,\\n address deployer\\n );\\n\\n /**\\n * @notice Address of the ERC721 bridge on this network.\\n */\\n address public immutable bridge;\\n\\n /**\\n * @notice Chain ID for the remote network.\\n */\\n uint256 public immutable remoteChainId;\\n\\n /**\\n * @notice Tracks addresses created by this factory.\\n */\\n mapping(address => bool) public isOptimismMintableERC721;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _bridge Address of the ERC721 bridge on this network.\\n */\\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 0, 0) {\\n require(\\n _bridge != address(0),\\n \\\"OptimismMintableERC721Factory: bridge cannot be address(0)\\\"\\n );\\n require(\\n _remoteChainId != 0,\\n \\\"OptimismMintableERC721Factory: remote chain id cannot be zero\\\"\\n );\\n\\n bridge = _bridge;\\n remoteChainId = _remoteChainId;\\n }\\n\\n /**\\n * @notice Creates an instance of the standard ERC721.\\n *\\n * @param _remoteToken Address of the corresponding token on the other domain.\\n * @param _name ERC721 name.\\n * @param _symbol ERC721 symbol.\\n */\\n function createOptimismMintableERC721(\\n address _remoteToken,\\n string memory _name,\\n string memory _symbol\\n ) external returns (address) {\\n require(\\n _remoteToken != address(0),\\n \\\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\\\"\\n );\\n\\n address localToken = address(\\n new OptimismMintableERC721(bridge, remoteChainId, _remoteToken, _name, _symbol)\\n );\\n\\n isOptimismMintableERC721[localToken] = true;\\n emit OptimismMintableERC721Created(localToken, _remoteToken, msg.sender);\\n\\n return localToken;\\n }\\n}\\n\",\"keccak256\":\"0xf53ee39e9ca7baa5d1c234e58068f9195be1d4c5180a4862356de86294563ba5\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b506040516139b33803806139b38339810160408190526100309161014d565b6001608052600060a081905260c0526001600160a01b0382166100c05760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a206260448201527f72696467652063616e6e6f74206265206164647265737328302900000000000060648201526084015b60405180910390fd5b806000036101365760405162461bcd60e51b815260206004820152603d60248201527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a207260448201527f656d6f746520636861696e2069642063616e6e6f74206265207a65726f00000060648201526084016100b7565b6001600160a01b0390911660e05261010052610187565b6000806040838503121561016057600080fd5b82516001600160a01b038116811461017757600080fd5b6020939093015192949293505050565b60805160a05160c05160e051610100516137da6101d960003960008181610138015261030a01526000818161011001526102e9015260006101c70152600061019c0152600061017101526137da6000f3fe60806040523480156200001157600080fd5b50600436106200006f5760003560e01c8063d97df6521162000056578063d97df65214620000cd578063e78cea92146200010a578063e9518196146200013257600080fd5b806354fd4d5014620000745780635572acae1462000096575b600080fd5b6200007e62000169565b6040516200008d9190620005dc565b60405180910390f35b620000bc620000a736600462000622565b60006020819052908152604090205460ff1681565b60405190151581526020016200008d565b620000e4620000de36600462000722565b62000214565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200008d565b620000e47f000000000000000000000000000000000000000000000000000000000000000081565b6200015a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016200008d565b6060620001967f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001c17f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001ec7f0000000000000000000000000000000000000000000000000000000000000000620003fa565b60405160200162000200939291906200079f565b604051602081830303815290604052905090565b600073ffffffffffffffffffffffffffffffffffffffff8416620002e5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a204c908201527f3120746f6b656e20616464726573732063616e6e6f742062652061646472657360648201527f7328302900000000000000000000000000000000000000000000000000000000608482015260a40160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008686866040516200033a906200054f565b6200034a9594939291906200081b565b604051809103906000f08015801562000367573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff8181166000818152602081815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590513381529394509188169290917fe72783bb8e0ca31286b85278da59684dd814df9762a52f0837f89edd1483b299910160405180910390a3949350505050565b6060816000036200043e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156200046e57806200045581620008ab565b9150620004669050600a8362000915565b915062000442565b60008167ffffffffffffffff8111156200048c576200048c62000640565b6040519080825280601f01601f191660200182016040528015620004b7576020820181803683370190505b5090505b84156200054757620004cf6001836200092c565b9150620004de600a8662000946565b620004eb9060306200095d565b60f81b81838151811062000503576200050362000978565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506200053f600a8662000915565b9450620004bb565b949350505050565b612dfd80620009a883390190565b60005b838110156200057a57818101518382015260200162000560565b838111156200058a576000848401525b50505050565b60008151808452620005aa8160208601602086016200055d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005f1602083018462000590565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061d57600080fd5b919050565b6000602082840312156200063557600080fd5b620005f182620005f8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200068157600080fd5b813567ffffffffffffffff808211156200069f576200069f62000640565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006e857620006e862000640565b816040528381528660208588010111156200070257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200073857600080fd5b6200074384620005f8565b9250602084013567ffffffffffffffff808211156200076157600080fd5b6200076f878388016200066f565b935060408601359150808211156200078657600080fd5b5062000795868287016200066f565b9150509250925092565b60008451620007b38184602089016200055d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551620007f1816001850160208a016200055d565b600192019182015283516200080e8160028401602088016200055d565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835286602084015280861660408401525060a060608301526200085c60a083018562000590565b828103608084015262000870818562000590565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620008df57620008df6200087c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082620009275762000927620008e6565b500490565b6000828210156200094157620009416200087c565b500390565b600082620009585762000958620008e6565b500690565b600082198211156200097357620009736200087c565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe60e06040523480156200001157600080fd5b5060405162002dfd38038062002dfd83398101604081905262000034916200062d565b8181600062000044838262000756565b50600162000053828262000756565b5050506001600160a01b038516620000d85760405162461bcd60e51b815260206004820152603360248201527f4f7074696d69736d4d696e7461626c654552433732313a20627269646765206360448201527f616e6e6f7420626520616464726573732830290000000000000000000000000060648201526084015b60405180910390fd5b83600003620001505760405162461bcd60e51b815260206004820152603660248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465206360448201527f6861696e2069642063616e6e6f74206265207a65726f000000000000000000006064820152608401620000cf565b6001600160a01b038316620001ce5760405162461bcd60e51b815260206004820152603960248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465207460448201527f6f6b656e2063616e6e6f742062652061646472657373283029000000000000006064820152608401620000cf565b60808490526001600160a01b0383811660a081905290861660c0526200020290601462000256602090811b62000dd217901c565b62000218856200041660201b62000ffb1760201c565b6040516020016200022b92919062000822565b604051602081830303815290604052600a90816200024a919062000756565b50505050505062000993565b6060600062000267836002620008ac565b62000274906002620008ce565b6001600160401b038111156200028e576200028e62000553565b6040519080825280601f01601f191660200182016040528015620002b9576020820181803683370190505b509050600360fc1b81600081518110620002d757620002d7620008e9565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110620003095762000309620008e9565b60200101906001600160f81b031916908160001a90535060006200032f846002620008ac565b6200033c906001620008ce565b90505b6001811115620003be576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620003745762000374620008e9565b1a60f81b8282815181106200038d576200038d620008e9565b60200101906001600160f81b031916908160001a90535060049490941c93620003b681620008ff565b90506200033f565b5083156200040f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620000cf565b9392505050565b6060816000036200043e5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156200046e5780620004558162000919565b9150620004669050600a836200094b565b915062000442565b6000816001600160401b038111156200048b576200048b62000553565b6040519080825280601f01601f191660200182016040528015620004b6576020820181803683370190505b5090505b84156200052e57620004ce60018362000962565b9150620004dd600a866200097c565b620004ea906030620008ce565b60f81b818381518110620005025762000502620008e9565b60200101906001600160f81b031916908160001a90535062000526600a866200094b565b9450620004ba565b949350505050565b80516001600160a01b03811681146200054e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620005865781810151838201526020016200056c565b8381111562000596576000848401525b50505050565b600082601f830112620005ae57600080fd5b81516001600160401b0380821115620005cb57620005cb62000553565b604051601f8301601f19908116603f01168101908282118183101715620005f657620005f662000553565b816040528381528660208588010111156200061057600080fd5b6200062384602083016020890162000569565b9695505050505050565b600080600080600060a086880312156200064657600080fd5b620006518662000536565b945060208601519350620006686040870162000536565b60608701519093506001600160401b03808211156200068657600080fd5b6200069489838a016200059c565b93506080880151915080821115620006ab57600080fd5b50620006ba888289016200059c565b9150509295509295909350565b600181811c90821680620006dc57607f821691505b602082108103620006fd57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200075157600081815260208120601f850160051c810160208610156200072c5750805b601f850160051c820191505b818110156200074d5782815560010162000738565b5050505b505050565b81516001600160401b0381111562000772576200077262000553565b6200078a81620007838454620006c7565b8462000703565b602080601f831160018114620007c25760008415620007a95750858301515b600019600386901b1c1916600185901b1785556200074d565b600085815260208120601f198616915b82811015620007f357888601518255948401946001909101908401620007d2565b5085821015620008125787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6832ba3432b932bab69d60b91b8152600083516200084881600985016020880162000569565b600160fe1b60099184019182015283516200086b81600a84016020880162000569565b712f746f6b656e5552493f75696e743235363d60701b600a9290910191820152601c01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620008c957620008c962000896565b500290565b60008219821115620008e457620008e462000896565b500190565b634e487b7160e01b600052603260045260246000fd5b60008162000911576200091162000896565b506000190190565b6000600182016200092e576200092e62000896565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826200095d576200095d62000935565b500490565b60008282101562000977576200097762000896565b500390565b6000826200098e576200098e62000935565b500690565b60805160a05160c05161242c620009d160003960008181610323015281816109f80152610ae6015260006102fc0152600061034a015261242c6000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c806395d89b41116100d8578063c87b56dd1161008c578063e78cea9211610066578063e78cea921461031e578063e951819614610345578063e985e9c51461036c57600080fd5b8063c87b56dd146102dc578063d547cfb7146102ef578063d6c0b2c4146102f757600080fd5b8063a1448194116100bd578063a1448194146102a3578063a22cb465146102b6578063b88d4fde146102c957600080fd5b806395d89b41146102885780639dc29fac1461029057600080fd5b806323b872dd1161013a5780634f6ccce7116101145780634f6ccce71461024f5780636352211e1461026257806370a082311461027557600080fd5b806323b872dd146102165780632f745c591461022957806342842e0e1461023c57600080fd5b8063081812fc1161016b578063081812fc146101c4578063095ea7b3146101ef57806318160ddd1461020457600080fd5b806301ffc9a71461018757806306fdde03146101af575b600080fd5b61019a610195366004611e6a565b6103a8565b60405190151581526020015b60405180910390f35b6101b7610457565b6040516101a69190611efd565b6101d76101d2366004611f10565b6104e9565b6040516001600160a01b0390911681526020016101a6565b6102026101fd366004611f45565b610594565b005b6008545b6040519081526020016101a6565b610202610224366004611f6f565b6106c5565b610208610237366004611f45565b61074c565b61020261024a366004611f6f565b6107f4565b61020861025d366004611f10565b61080f565b6101d7610270366004611f10565b6108b3565b610208610283366004611fab565b610944565b6101b76109de565b61020261029e366004611f45565b6109ed565b6102026102b1366004611f45565b610adb565b6102026102c4366004611fc6565b610bbe565b6102026102d7366004612031565b610bcd565b6101b76102ea366004611f10565b610c5b565b6101b7610d44565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6102087f000000000000000000000000000000000000000000000000000000000000000081565b61019a61037a36600461212b565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fe49bc7f8000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841682148061044057507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b8061044f575061044f84611130565b949350505050565b6060600080546104669061215e565b80601f01602080910402602001604051908101604052809291908181526020018280546104929061215e565b80156104df5780601f106104b4576101008083540402835291602001916104df565b820191906000526020600020905b8154815290600101906020018083116104c257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166105785760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061059f826108b3565b9050806001600160a01b0316836001600160a01b0316036106285760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161056f565b336001600160a01b03821614806106445750610644813361037a565b6106b65760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161056f565b6106c08383611186565b505050565b6106cf338261120c565b6107415760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b6106c0838383611313565b600061075783610944565b82106107cb5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e6473000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6106c083838360405180602001604052806000815250610bcd565b600061081a60085490565b821061088e5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e64730000000000000000000000000000000000000000606482015260840161056f565b600882815481106108a1576108a16121b1565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b03168061093e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e0000000000000000000000000000000000000000000000606482015260840161056f565b92915050565b60006001600160a01b0382166109c25760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f206164647265737300000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b031660009081526003602052604090205490565b6060600180546104669061215e565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a8b5760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610a9481611503565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca582604051610acf91815260200190565b60405180910390a25050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b795760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610b8382826115c2565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610acf91815260200190565b610bc93383836115dc565b5050565b610bd7338361120c565b610c495760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b610c55848484846116c8565b50505050565b6000818152600260205260409020546060906001600160a01b0316610ce85760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000606482015260840161056f565b6000610cf2611751565b90506000815111610d125760405180602001604052806000815250610d3d565b80610d1c84610ffb565b604051602001610d2d9291906121e0565b6040516020818303038152906040525b9392505050565b600a8054610d519061215e565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7d9061215e565b8015610dca5780601f10610d9f57610100808354040283529160200191610dca565b820191906000526020600020905b815481529060010190602001808311610dad57829003601f168201915b505050505081565b60606000610de183600261223e565b610dec90600261227b565b67ffffffffffffffff811115610e0457610e04612002565b6040519080825280601f01601f191660200182016040528015610e2e576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110610e6557610e656121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110610ec857610ec86121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000610f0484600261223e565b610f0f90600161227b565b90505b6001811115610fac577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110610f5057610f506121b1565b1a60f81b828281518110610f6657610f666121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93610fa581612293565b9050610f12565b508315610d3d5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161056f565b60608160000361103e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156110685780611052816122c8565b91506110619050600a8361232f565b9150611042565b60008167ffffffffffffffff81111561108357611083612002565b6040519080825280601f01601f1916602001820160405280156110ad576020820181803683370190505b5090505b841561044f576110c2600183612343565b91506110cf600a8661235a565b6110da90603061227b565b60f81b8183815181106110ef576110ef6121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611129600a8661232f565b94506110b1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d6300000000000000000000000000000000000000000000000000000000148061093e575061093e82611760565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841690811790915581906111d3826108b3565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166112965760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606482015260840161056f565b60006112a1836108b3565b9050806001600160a01b0316846001600160a01b031614806112e857506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b8061044f5750836001600160a01b0316611301846104e9565b6001600160a01b031614949350505050565b826001600160a01b0316611326826108b3565b6001600160a01b0316146113a25760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e6572000000000000000000000000000000000000000000000000000000606482015260840161056f565b6001600160a01b03821661141d5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161056f565b611428838383611843565b611433600082611186565b6001600160a01b038316600090815260036020526040812080546001929061145c908490612343565b90915550506001600160a01b038216600090815260036020526040812080546001929061148a90849061227b565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061150e826108b3565b905061151c81600084611843565b611527600083611186565b6001600160a01b0381166000908152600360205260408120805460019290611550908490612343565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b610bc98282604051806020016040528060008152506118fb565b816001600160a01b0316836001600160a01b03160361163d5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161056f565b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6116d3848484611313565b6116df84848484611984565b610c555760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b6060600a80546104669061215e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806117f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061093e57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461093e565b6001600160a01b03831661189e5761189981600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6118c1565b816001600160a01b0316836001600160a01b0316146118c1576118c18382611b43565b6001600160a01b0382166118d8576106c081611be0565b826001600160a01b0316826001600160a01b0316146106c0576106c08282611c8f565b6119058383611cd3565b6119126000848484611984565b6106c05760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b60006001600160a01b0384163b15611b38576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a02906119e190339089908890889060040161236e565b6020604051808303816000875af1925050508015611a3a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611a37918101906123aa565b60015b611aed573d808015611a68576040519150601f19603f3d011682016040523d82523d6000602084013e611a6d565b606091505b508051600003611ae55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a020000000000000000000000000000000000000000000000000000000014905061044f565b506001949350505050565b60006001611b5084610944565b611b5a9190612343565b600083815260076020526040902054909150808214611bad576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611bf290600190612343565b60008381526009602052604081205460088054939450909284908110611c1a57611c1a6121b1565b906000526020600020015490508060088381548110611c3b57611c3b6121b1565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611c7357611c736123c7565b6001900381819060005260206000200160009055905550505050565b6000611c9a83610944565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b038216611d295760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161056f565b6000818152600260205260409020546001600160a01b031615611d8e5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056f565b611d9a60008383611843565b6001600160a01b0382166000908152600360205260408120805460019290611dc390849061227b565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611e6757600080fd5b50565b600060208284031215611e7c57600080fd5b8135610d3d81611e39565b60005b83811015611ea2578181015183820152602001611e8a565b83811115610c555750506000910152565b60008151808452611ecb816020860160208601611e87565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d3d6020830184611eb3565b600060208284031215611f2257600080fd5b5035919050565b80356001600160a01b0381168114611f4057600080fd5b919050565b60008060408385031215611f5857600080fd5b611f6183611f29565b946020939093013593505050565b600080600060608486031215611f8457600080fd5b611f8d84611f29565b9250611f9b60208501611f29565b9150604084013590509250925092565b600060208284031215611fbd57600080fd5b610d3d82611f29565b60008060408385031215611fd957600080fd5b611fe283611f29565b915060208301358015158114611ff757600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561204757600080fd5b61205085611f29565b935061205e60208601611f29565b925060408501359150606085013567ffffffffffffffff8082111561208257600080fd5b818701915087601f83011261209657600080fd5b8135818111156120a8576120a8612002565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156120ee576120ee612002565b816040528281528a602084870101111561210757600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561213e57600080fd5b61214783611f29565b915061215560208401611f29565b90509250929050565b600181811c9082168061217257607f821691505b6020821081036121ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600083516121f2818460208801611e87565b835190830190612206818360208801611e87565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156122765761227661220f565b500290565b6000821982111561228e5761228e61220f565b500190565b6000816122a2576122a261220f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f9576122f961220f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261233e5761233e612300565b500490565b6000828210156123555761235561220f565b500390565b60008261236957612369612300565b500690565b60006001600160a01b038087168352808616602084015250836040830152608060608301526123a06080830184611eb3565b9695505050505050565b6000602082840312156123bc57600080fd5b8151610d3d81611e39565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220091cfc6e67938e5e9e61881af7ded22673b926104a9d05247aaec2f673e28e7364736f6c634300080f0033a2646970667358221220e0ec23cedfe5d74b2d927547b5882cd7e2b775e04cdebb66d2280c7da8786df664736f6c634300080f0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200006f5760003560e01c8063d97df6521162000056578063d97df65214620000cd578063e78cea92146200010a578063e9518196146200013257600080fd5b806354fd4d5014620000745780635572acae1462000096575b600080fd5b6200007e62000169565b6040516200008d9190620005dc565b60405180910390f35b620000bc620000a736600462000622565b60006020819052908152604090205460ff1681565b60405190151581526020016200008d565b620000e4620000de36600462000722565b62000214565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200008d565b620000e47f000000000000000000000000000000000000000000000000000000000000000081565b6200015a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016200008d565b6060620001967f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001c17f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001ec7f0000000000000000000000000000000000000000000000000000000000000000620003fa565b60405160200162000200939291906200079f565b604051602081830303815290604052905090565b600073ffffffffffffffffffffffffffffffffffffffff8416620002e5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a204c908201527f3120746f6b656e20616464726573732063616e6e6f742062652061646472657360648201527f7328302900000000000000000000000000000000000000000000000000000000608482015260a40160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008686866040516200033a906200054f565b6200034a9594939291906200081b565b604051809103906000f08015801562000367573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff8181166000818152602081815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590513381529394509188169290917fe72783bb8e0ca31286b85278da59684dd814df9762a52f0837f89edd1483b299910160405180910390a3949350505050565b6060816000036200043e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156200046e57806200045581620008ab565b9150620004669050600a8362000915565b915062000442565b60008167ffffffffffffffff8111156200048c576200048c62000640565b6040519080825280601f01601f191660200182016040528015620004b7576020820181803683370190505b5090505b84156200054757620004cf6001836200092c565b9150620004de600a8662000946565b620004eb9060306200095d565b60f81b81838151811062000503576200050362000978565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506200053f600a8662000915565b9450620004bb565b949350505050565b612dfd80620009a883390190565b60005b838110156200057a57818101518382015260200162000560565b838111156200058a576000848401525b50505050565b60008151808452620005aa8160208601602086016200055d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005f1602083018462000590565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061d57600080fd5b919050565b6000602082840312156200063557600080fd5b620005f182620005f8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200068157600080fd5b813567ffffffffffffffff808211156200069f576200069f62000640565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006e857620006e862000640565b816040528381528660208588010111156200070257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200073857600080fd5b6200074384620005f8565b9250602084013567ffffffffffffffff808211156200076157600080fd5b6200076f878388016200066f565b935060408601359150808211156200078657600080fd5b5062000795868287016200066f565b9150509250925092565b60008451620007b38184602089016200055d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551620007f1816001850160208a016200055d565b600192019182015283516200080e8160028401602088016200055d565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835286602084015280861660408401525060a060608301526200085c60a083018562000590565b828103608084015262000870818562000590565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620008df57620008df6200087c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082620009275762000927620008e6565b500490565b6000828210156200094157620009416200087c565b500390565b600082620009585762000958620008e6565b500690565b600082198211156200097357620009736200087c565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe60e06040523480156200001157600080fd5b5060405162002dfd38038062002dfd83398101604081905262000034916200062d565b8181600062000044838262000756565b50600162000053828262000756565b5050506001600160a01b038516620000d85760405162461bcd60e51b815260206004820152603360248201527f4f7074696d69736d4d696e7461626c654552433732313a20627269646765206360448201527f616e6e6f7420626520616464726573732830290000000000000000000000000060648201526084015b60405180910390fd5b83600003620001505760405162461bcd60e51b815260206004820152603660248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465206360448201527f6861696e2069642063616e6e6f74206265207a65726f000000000000000000006064820152608401620000cf565b6001600160a01b038316620001ce5760405162461bcd60e51b815260206004820152603960248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465207460448201527f6f6b656e2063616e6e6f742062652061646472657373283029000000000000006064820152608401620000cf565b60808490526001600160a01b0383811660a081905290861660c0526200020290601462000256602090811b62000dd217901c565b62000218856200041660201b62000ffb1760201c565b6040516020016200022b92919062000822565b604051602081830303815290604052600a90816200024a919062000756565b50505050505062000993565b6060600062000267836002620008ac565b62000274906002620008ce565b6001600160401b038111156200028e576200028e62000553565b6040519080825280601f01601f191660200182016040528015620002b9576020820181803683370190505b509050600360fc1b81600081518110620002d757620002d7620008e9565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110620003095762000309620008e9565b60200101906001600160f81b031916908160001a90535060006200032f846002620008ac565b6200033c906001620008ce565b90505b6001811115620003be576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620003745762000374620008e9565b1a60f81b8282815181106200038d576200038d620008e9565b60200101906001600160f81b031916908160001a90535060049490941c93620003b681620008ff565b90506200033f565b5083156200040f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620000cf565b9392505050565b6060816000036200043e5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156200046e5780620004558162000919565b9150620004669050600a836200094b565b915062000442565b6000816001600160401b038111156200048b576200048b62000553565b6040519080825280601f01601f191660200182016040528015620004b6576020820181803683370190505b5090505b84156200052e57620004ce60018362000962565b9150620004dd600a866200097c565b620004ea906030620008ce565b60f81b818381518110620005025762000502620008e9565b60200101906001600160f81b031916908160001a90535062000526600a866200094b565b9450620004ba565b949350505050565b80516001600160a01b03811681146200054e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620005865781810151838201526020016200056c565b8381111562000596576000848401525b50505050565b600082601f830112620005ae57600080fd5b81516001600160401b0380821115620005cb57620005cb62000553565b604051601f8301601f19908116603f01168101908282118183101715620005f657620005f662000553565b816040528381528660208588010111156200061057600080fd5b6200062384602083016020890162000569565b9695505050505050565b600080600080600060a086880312156200064657600080fd5b620006518662000536565b945060208601519350620006686040870162000536565b60608701519093506001600160401b03808211156200068657600080fd5b6200069489838a016200059c565b93506080880151915080821115620006ab57600080fd5b50620006ba888289016200059c565b9150509295509295909350565b600181811c90821680620006dc57607f821691505b602082108103620006fd57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200075157600081815260208120601f850160051c810160208610156200072c5750805b601f850160051c820191505b818110156200074d5782815560010162000738565b5050505b505050565b81516001600160401b0381111562000772576200077262000553565b6200078a81620007838454620006c7565b8462000703565b602080601f831160018114620007c25760008415620007a95750858301515b600019600386901b1c1916600185901b1785556200074d565b600085815260208120601f198616915b82811015620007f357888601518255948401946001909101908401620007d2565b5085821015620008125787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6832ba3432b932bab69d60b91b8152600083516200084881600985016020880162000569565b600160fe1b60099184019182015283516200086b81600a84016020880162000569565b712f746f6b656e5552493f75696e743235363d60701b600a9290910191820152601c01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620008c957620008c962000896565b500290565b60008219821115620008e457620008e462000896565b500190565b634e487b7160e01b600052603260045260246000fd5b60008162000911576200091162000896565b506000190190565b6000600182016200092e576200092e62000896565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826200095d576200095d62000935565b500490565b60008282101562000977576200097762000896565b500390565b6000826200098e576200098e62000935565b500690565b60805160a05160c05161242c620009d160003960008181610323015281816109f80152610ae6015260006102fc0152600061034a015261242c6000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c806395d89b41116100d8578063c87b56dd1161008c578063e78cea9211610066578063e78cea921461031e578063e951819614610345578063e985e9c51461036c57600080fd5b8063c87b56dd146102dc578063d547cfb7146102ef578063d6c0b2c4146102f757600080fd5b8063a1448194116100bd578063a1448194146102a3578063a22cb465146102b6578063b88d4fde146102c957600080fd5b806395d89b41146102885780639dc29fac1461029057600080fd5b806323b872dd1161013a5780634f6ccce7116101145780634f6ccce71461024f5780636352211e1461026257806370a082311461027557600080fd5b806323b872dd146102165780632f745c591461022957806342842e0e1461023c57600080fd5b8063081812fc1161016b578063081812fc146101c4578063095ea7b3146101ef57806318160ddd1461020457600080fd5b806301ffc9a71461018757806306fdde03146101af575b600080fd5b61019a610195366004611e6a565b6103a8565b60405190151581526020015b60405180910390f35b6101b7610457565b6040516101a69190611efd565b6101d76101d2366004611f10565b6104e9565b6040516001600160a01b0390911681526020016101a6565b6102026101fd366004611f45565b610594565b005b6008545b6040519081526020016101a6565b610202610224366004611f6f565b6106c5565b610208610237366004611f45565b61074c565b61020261024a366004611f6f565b6107f4565b61020861025d366004611f10565b61080f565b6101d7610270366004611f10565b6108b3565b610208610283366004611fab565b610944565b6101b76109de565b61020261029e366004611f45565b6109ed565b6102026102b1366004611f45565b610adb565b6102026102c4366004611fc6565b610bbe565b6102026102d7366004612031565b610bcd565b6101b76102ea366004611f10565b610c5b565b6101b7610d44565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6101d77f000000000000000000000000000000000000000000000000000000000000000081565b6102087f000000000000000000000000000000000000000000000000000000000000000081565b61019a61037a36600461212b565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fe49bc7f8000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841682148061044057507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b8061044f575061044f84611130565b949350505050565b6060600080546104669061215e565b80601f01602080910402602001604051908101604052809291908181526020018280546104929061215e565b80156104df5780601f106104b4576101008083540402835291602001916104df565b820191906000526020600020905b8154815290600101906020018083116104c257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166105785760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061059f826108b3565b9050806001600160a01b0316836001600160a01b0316036106285760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161056f565b336001600160a01b03821614806106445750610644813361037a565b6106b65760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161056f565b6106c08383611186565b505050565b6106cf338261120c565b6107415760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b6106c0838383611313565b600061075783610944565b82106107cb5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e6473000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6106c083838360405180602001604052806000815250610bcd565b600061081a60085490565b821061088e5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e64730000000000000000000000000000000000000000606482015260840161056f565b600882815481106108a1576108a16121b1565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b03168061093e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e0000000000000000000000000000000000000000000000606482015260840161056f565b92915050565b60006001600160a01b0382166109c25760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f206164647265737300000000000000000000000000000000000000000000606482015260840161056f565b506001600160a01b031660009081526003602052604090205490565b6060600180546104669061215e565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a8b5760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610a9481611503565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca582604051610acf91815260200190565b60405180910390a25050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b795760405162461bcd60e51b815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e000000000000606482015260840161056f565b610b8382826115c2565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610acf91815260200190565b610bc93383836115dc565b5050565b610bd7338361120c565b610c495760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606482015260840161056f565b610c55848484846116c8565b50505050565b6000818152600260205260409020546060906001600160a01b0316610ce85760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000606482015260840161056f565b6000610cf2611751565b90506000815111610d125760405180602001604052806000815250610d3d565b80610d1c84610ffb565b604051602001610d2d9291906121e0565b6040516020818303038152906040525b9392505050565b600a8054610d519061215e565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7d9061215e565b8015610dca5780601f10610d9f57610100808354040283529160200191610dca565b820191906000526020600020905b815481529060010190602001808311610dad57829003601f168201915b505050505081565b60606000610de183600261223e565b610dec90600261227b565b67ffffffffffffffff811115610e0457610e04612002565b6040519080825280601f01601f191660200182016040528015610e2e576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110610e6557610e656121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110610ec857610ec86121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000610f0484600261223e565b610f0f90600161227b565b90505b6001811115610fac577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110610f5057610f506121b1565b1a60f81b828281518110610f6657610f666121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93610fa581612293565b9050610f12565b508315610d3d5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161056f565b60608160000361103e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156110685780611052816122c8565b91506110619050600a8361232f565b9150611042565b60008167ffffffffffffffff81111561108357611083612002565b6040519080825280601f01601f1916602001820160405280156110ad576020820181803683370190505b5090505b841561044f576110c2600183612343565b91506110cf600a8661235a565b6110da90603061227b565b60f81b8183815181106110ef576110ef6121b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611129600a8661232f565b94506110b1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d6300000000000000000000000000000000000000000000000000000000148061093e575061093e82611760565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841690811790915581906111d3826108b3565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166112965760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606482015260840161056f565b60006112a1836108b3565b9050806001600160a01b0316846001600160a01b031614806112e857506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b8061044f5750836001600160a01b0316611301846104e9565b6001600160a01b031614949350505050565b826001600160a01b0316611326826108b3565b6001600160a01b0316146113a25760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e6572000000000000000000000000000000000000000000000000000000606482015260840161056f565b6001600160a01b03821661141d5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161056f565b611428838383611843565b611433600082611186565b6001600160a01b038316600090815260036020526040812080546001929061145c908490612343565b90915550506001600160a01b038216600090815260036020526040812080546001929061148a90849061227b565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061150e826108b3565b905061151c81600084611843565b611527600083611186565b6001600160a01b0381166000908152600360205260408120805460019290611550908490612343565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b610bc98282604051806020016040528060008152506118fb565b816001600160a01b0316836001600160a01b03160361163d5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161056f565b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6116d3848484611313565b6116df84848484611984565b610c555760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b6060600a80546104669061215e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806117f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061093e57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461093e565b6001600160a01b03831661189e5761189981600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6118c1565b816001600160a01b0316836001600160a01b0316146118c1576118c18382611b43565b6001600160a01b0382166118d8576106c081611be0565b826001600160a01b0316826001600160a01b0316146106c0576106c08282611c8f565b6119058383611cd3565b6119126000848484611984565b6106c05760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b60006001600160a01b0384163b15611b38576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a02906119e190339089908890889060040161236e565b6020604051808303816000875af1925050508015611a3a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611a37918101906123aa565b60015b611aed573d808015611a68576040519150601f19603f3d011682016040523d82523d6000602084013e611a6d565b606091505b508051600003611ae55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e7465720000000000000000000000000000606482015260840161056f565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a020000000000000000000000000000000000000000000000000000000014905061044f565b506001949350505050565b60006001611b5084610944565b611b5a9190612343565b600083815260076020526040902054909150808214611bad576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611bf290600190612343565b60008381526009602052604081205460088054939450909284908110611c1a57611c1a6121b1565b906000526020600020015490508060088381548110611c3b57611c3b6121b1565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611c7357611c736123c7565b6001900381819060005260206000200160009055905550505050565b6000611c9a83610944565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b038216611d295760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161056f565b6000818152600260205260409020546001600160a01b031615611d8e5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056f565b611d9a60008383611843565b6001600160a01b0382166000908152600360205260408120805460019290611dc390849061227b565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611e6757600080fd5b50565b600060208284031215611e7c57600080fd5b8135610d3d81611e39565b60005b83811015611ea2578181015183820152602001611e8a565b83811115610c555750506000910152565b60008151808452611ecb816020860160208601611e87565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d3d6020830184611eb3565b600060208284031215611f2257600080fd5b5035919050565b80356001600160a01b0381168114611f4057600080fd5b919050565b60008060408385031215611f5857600080fd5b611f6183611f29565b946020939093013593505050565b600080600060608486031215611f8457600080fd5b611f8d84611f29565b9250611f9b60208501611f29565b9150604084013590509250925092565b600060208284031215611fbd57600080fd5b610d3d82611f29565b60008060408385031215611fd957600080fd5b611fe283611f29565b915060208301358015158114611ff757600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561204757600080fd5b61205085611f29565b935061205e60208601611f29565b925060408501359150606085013567ffffffffffffffff8082111561208257600080fd5b818701915087601f83011261209657600080fd5b8135818111156120a8576120a8612002565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156120ee576120ee612002565b816040528281528a602084870101111561210757600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561213e57600080fd5b61214783611f29565b915061215560208401611f29565b90509250929050565b600181811c9082168061217257607f821691505b6020821081036121ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600083516121f2818460208801611e87565b835190830190612206818360208801611e87565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156122765761227661220f565b500290565b6000821982111561228e5761228e61220f565b500190565b6000816122a2576122a261220f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f9576122f961220f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261233e5761233e612300565b500490565b6000828210156123555761235561220f565b500390565b60008261236957612369612300565b500690565b60006001600160a01b038087168352808616602084015250836040830152608060608301526123a06080830184611eb3565b9695505050505050565b6000602082840312156123bc57600080fd5b8151610d3d81611e39565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220091cfc6e67938e5e9e61881af7ded22673b926104a9d05247aaec2f673e28e7364736f6c634300080f0033a2646970667358221220e0ec23cedfe5d74b2d927547b5882cd7e2b775e04cdebb66d2280c7da8786df664736f6c634300080f0033", + "devdoc": { + "events": { + "OptimismMintableERC721Created(address,address,address)": { + "params": { + "deployer": "Address of the initiator of the deployment", + "localToken": "Address of the token on the this domain.", + "remoteToken": "Address of the token on the remote domain." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "custom:semver": "1.0.0", + "params": { + "_bridge": "Address of the ERC721 bridge on this network." + } + }, + "createOptimismMintableERC721(address,string,string)": { + "params": { + "_name": "ERC721 name.", + "_remoteToken": "Address of the corresponding token on the other domain.", + "_symbol": "ERC721 symbol." + } + }, + "version()": { + "returns": { + "_0": "Semver contract version as a string." + } + } + }, + "title": "OptimismMintableERC721Factory", + "version": 1 + }, + "userdoc": { + "events": { + "OptimismMintableERC721Created(address,address,address)": { + "notice": "Emitted whenever a new OptimismMintableERC721 contract is created." + } + }, + "kind": "user", + "methods": { + "bridge()": { + "notice": "Address of the ERC721 bridge on this network." + }, + "createOptimismMintableERC721(address,string,string)": { + "notice": "Creates an instance of the standard ERC721." + }, + "isOptimismMintableERC721(address)": { + "notice": "Tracks addresses created by this factory." + }, + "remoteChainId()": { + "notice": "Chain ID for the remote network." + }, + "version()": { + "notice": "Returns the full semver contract version." + } + }, + "notice": "Factory contract for creating OptimismMintableERC721 contracts.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 8543, + "contract": "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory", + "label": "isOptimismMintableERC721", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism/OptimismMintableERC721FactoryProxy.json b/packages/contracts-periphery/deployments/optimism/OptimismMintableERC721FactoryProxy.json new file mode 100644 index 0000000000000..4c0e4160aa01e --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism/OptimismMintableERC721FactoryProxy.json @@ -0,0 +1,257 @@ +{ + "address": "0x4482B6510dF4C723Bdf80c4441dBDbc855AB29AC", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xe730ca7b4123d14a445606ce0cf449b3c73c12da907c765c63df04d68f3427bb", + "receipt": { + "to": null, + "from": "0x53A6eecC2dD4795Fcc68940ddc6B4d53Bd88Bd9E", + "contractAddress": "0x4482B6510dF4C723Bdf80c4441dBDbc855AB29AC", + "transactionIndex": 0, + "gasUsed": "532674", + "logsBloom": "0x00000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000008000000020000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc8610148d3e013d22ad9c3d52f6f96c01c9ba33a71bcc2e58dbe058ab5766f82", + "transactionHash": "0xe730ca7b4123d14a445606ce0cf449b3c73c12da907c765c63df04d68f3427bb", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 27396072, + "transactionHash": "0xe730ca7b4123d14a445606ce0cf449b3c73c12da907c765c63df04d68f3427bb", + "address": "0x4482B6510dF4C723Bdf80c4441dBDbc855AB29AC", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000053a6eecc2dd4795fcc68940ddc6b4d53bd88bd9e", + "logIndex": 0, + "blockHash": "0xc8610148d3e013d22ad9c3d52f6f96c01c9ba33a71bcc2e58dbe058ab5766f82" + } + ], + "blockNumber": 27396072, + "cumulativeGasUsed": "532674", + "status": 1, + "byzantium": true + }, + "args": [ + "0x53A6eecC2dD4795Fcc68940ddc6B4d53Bd88Bd9E" + ], + "numDeployments": 1, + "solcInputHash": "ab9b77493f35e63b7a63fb2fa8d618b4", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"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\"}}},\"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.\"}}},\"title\":\"Proxy\",\"version\":1},\"userdoc\":{\"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.\"}},\"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.\"},\"implementation()\":{\"notice\":\"Queries the implementation address.\"},\"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.\"}},\"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.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title Proxy\\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\\n * if the caller is address(0), meaning that the call originated from an off-chain\\n * simulation.\\n */\\ncontract Proxy {\\n /**\\n * @notice The storage slot that holds the address of the implementation.\\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n */\\n bytes32 internal constant IMPLEMENTATION_KEY =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @notice The storage slot that holds the address of the owner.\\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n */\\n bytes32 internal constant OWNER_KEY =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @notice An event that is emitted each time the implementation is changed. This event is part\\n * of the EIP-1967 specification.\\n *\\n * @param implementation The address of the implementation contract\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\\n * EIP-1967 specification.\\n *\\n * @param previousAdmin The previous owner of the contract\\n * @param newAdmin The new owner of the contract\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\\n * eth_call to interact with this proxy without needing to use low-level storage\\n * inspection. We assume that nobody is able to trigger calls from address(0) during\\n * normal EVM execution.\\n */\\n modifier proxyCallIfNotAdmin() {\\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\\n _;\\n } else {\\n // This WILL halt the call frame on completion.\\n _doProxyCall();\\n }\\n }\\n\\n /**\\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\\n * EIP-1967 admin storage slot so that accidental storage collision with the\\n * implementation is not possible.\\n *\\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\\n * transparent proxy interface.\\n */\\n constructor(address _admin) {\\n _changeAdmin(_admin);\\n }\\n\\n // slither-disable-next-line locked-ether\\n receive() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n // slither-disable-next-line locked-ether\\n fallback() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n /**\\n * @notice Set the implementation contract address. The code at the given address will execute\\n * when this contract is called.\\n *\\n * @param _implementation Address of the implementation contract.\\n */\\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\\n _setImplementation(_implementation);\\n }\\n\\n /**\\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\\n * atomic execution of initialization-based upgrades.\\n *\\n * @param _implementation Address of the implementation contract.\\n * @param _data Calldata to delegatecall the new implementation with.\\n */\\n function upgradeToAndCall(address _implementation, bytes calldata _data)\\n external\\n payable\\n proxyCallIfNotAdmin\\n returns (bytes memory)\\n {\\n _setImplementation(_implementation);\\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\\n require(success, \\\"Proxy: delegatecall to new implementation contract failed\\\");\\n return returndata;\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\\n _changeAdmin(_admin);\\n }\\n\\n /**\\n * @notice Gets the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function admin() external proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() external proxyCallIfNotAdmin returns (address) {\\n return _getImplementation();\\n }\\n\\n /**\\n * @notice Sets the implementation address.\\n *\\n * @param _implementation New implementation address.\\n */\\n function _setImplementation(address _implementation) internal {\\n assembly {\\n sstore(IMPLEMENTATION_KEY, _implementation)\\n }\\n emit Upgraded(_implementation);\\n }\\n\\n /**\\n * @notice Changes the owner of the proxy contract.\\n *\\n * @param _admin New owner of the proxy contract.\\n */\\n function _changeAdmin(address _admin) internal {\\n address previous = _getAdmin();\\n assembly {\\n sstore(OWNER_KEY, _admin)\\n }\\n emit AdminChanged(previous, _admin);\\n }\\n\\n /**\\n * @notice Performs the proxy call via a delegatecall.\\n */\\n function _doProxyCall() internal {\\n address impl = _getImplementation();\\n require(impl != address(0), \\\"Proxy: implementation not initialized\\\");\\n\\n assembly {\\n // Copy calldata into memory at 0x0....calldatasize.\\n calldatacopy(0x0, 0x0, calldatasize())\\n\\n // Perform the delegatecall, make sure to pass all available gas.\\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\\n\\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\\n // overwrite the calldata that we just copied into memory but that doesn't really\\n // matter because we'll be returning in a second anyway.\\n returndatacopy(0x0, 0x0, returndatasize())\\n\\n // Success == 0 means a revert. We'll revert too and pass the data up.\\n if iszero(success) {\\n revert(0x0, returndatasize())\\n }\\n\\n // Otherwise we'll just return and pass the data up.\\n return(0x0, returndatasize())\\n }\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n address impl;\\n assembly {\\n impl := sload(IMPLEMENTATION_KEY)\\n }\\n return impl;\\n }\\n\\n /**\\n * @notice Queries the owner of the proxy contract.\\n *\\n * @return Owner address.\\n */\\n function _getAdmin() internal view returns (address) {\\n address owner;\\n assembly {\\n owner := sload(OWNER_KEY)\\n }\\n return owner;\\n }\\n}\\n\",\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5060405161094138038061094183398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206109218339815191525490565b600080516020610921833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610830806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea2646970667358221220120210f19dd8be0e46312b3b9a2148bbb98ec24cce2aa05af1c3d1fe69f55b2b64736f6c634300080f0033", + "devdoc": { + "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" + } + } + }, + "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." + } + } + }, + "title": "Proxy", + "version": 1 + }, + "userdoc": { + "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." + } + }, + "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." + }, + "implementation()": { + "notice": "Queries the implementation address." + }, + "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." + } + }, + "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.", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/deployments/optimism/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json b/packages/contracts-periphery/deployments/optimism/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json new file mode 100644 index 0000000000000..91d5f99068af8 --- /dev/null +++ b/packages/contracts-periphery/deployments/optimism/solcInputs/ab9b77493f35e63b7a63fb2fa8d618b4.json @@ -0,0 +1,173 @@ +{ + "language": "Solidity", + "sources": { + "contracts/L1/L1ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L1ERC721Bridge\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as an escrow for ERC721 tokens deposited into L2.\n */\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\n * by ID was deposited for a given L2 token.\n */\n mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L2. Data supplied here will not be used to\n * execute any code on L2 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L1ERC721Bridge: local token cannot be self\");\n\n // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\n require(\n deposits[_localToken][_remoteToken][_tokenId] == true,\n \"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\"\n );\n\n // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\n // Bridge.\n deposits[_localToken][_remoteToken][_tokenId] = false;\n\n // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\n // withdrawer.\n IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\n bytes memory message = abi.encodeWithSelector(\n L2ERC721Bridge.finalizeBridgeERC721.selector,\n _remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Lock token into bridge\n deposits[_localToken][_remoteToken][_tokenId] = true;\n IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\n\n // Send calldata into L2\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "contracts/universal/op-erc721/ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n CrossDomainMessenger\n} from \"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title ERC721Bridge\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\n */\nabstract contract ERC721Bridge {\n /**\n * @notice Emitted when an ERC721 bridge to the other network is initiated.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC721 bridge from the other network is finalized.\n *\n * @param localToken Address of the token on this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param from Address that initiated bridging action.\n * @param to Address to receive the token.\n * @param tokenId ID of the specific token deposited.\n * @param extraData Extra data for use on the client-side.\n */\n event ERC721BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 tokenId,\n bytes extraData\n );\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable messenger;\n\n /**\n * @notice Address of the bridge on the other network.\n */\n address public immutable otherBridge;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[49] private __gap;\n\n /**\n * @notice Ensures that the caller is a cross-chain message from the other bridge.\n */\n modifier onlyOtherBridge() {\n require(\n msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\n \"ERC721Bridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge) {\n require(_messenger != address(0), \"ERC721Bridge: messenger cannot be address(0)\");\n require(_otherBridge != address(0), \"ERC721Bridge: other bridge cannot be address(0)\");\n\n messenger = CrossDomainMessenger(_messenger);\n otherBridge = _otherBridge;\n }\n\n /**\n * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\n * this function can only be called by EOAs. Smart contract wallets should use the\n * `bridgeERC721To` function after ensuring that the recipient address on the remote\n * chain exists. Also note that the current owner of the token on this chain must\n * approve this contract to operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721(\n address _localToken,\n address _remoteToken,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n // Modifier requiring sender to be EOA. This prevents against a user error that would occur\n // if the sender is a smart contract wallet that has a different address on the remote chain\n // (or doesn't have an address on the remote chain at all). The user would fail to receive\n // the NFT if they use this function because it sends the NFT to the same address as the\n // caller. This check could be bypassed by a malicious contract via initcode, but it takes\n // care of the user error we want to avoid.\n require(!Address.isContract(msg.sender), \"ERC721Bridge: account is not externally owned\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\n * that the current owner of the token on this chain must approve this contract to\n * operate the NFT before it can be bridged.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other chain. Data supplied here will not\n * be used to execute any code on the other chain and is only emitted as\n * extra data for the convenience of off-chain tooling.\n */\n function bridgeERC721To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external {\n require(_to != address(0), \"ERC721Bridge: nft recipient cannot be address(0)\");\n\n _initiateBridgeERC721(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _tokenId,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Internal function for initiating a token bridge to the other domain.\n *\n * @param _localToken Address of the ERC721 on this domain.\n * @param _remoteToken Address of the ERC721 on the remote domain.\n * @param _from Address of the sender on this domain.\n * @param _to Address to receive the token on the other domain.\n * @param _tokenId Token ID to bridge.\n * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n * @param _extraData Optional data to forward to the other domain. Data supplied here will\n * not be used to execute any code on the other domain and is only emitted\n * as extra data for the convenience of off-chain tooling.\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal virtual;\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "contracts/L2/L2ERC721Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/op-erc721/IOptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L2ERC721Bridge\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\n * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n * acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\n * This contract also acts as a burner for tokens being withdrawn.\n * **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n * bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\n * wait for the one-week challenge period to elapse before their Optimism-native NFT\n * can be refunded on L2.\n */\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the CrossDomainMessenger on this network.\n * @param _otherBridge Address of the ERC721 bridge on the other network.\n */\n constructor(address _messenger, address _otherBridge)\n Semver(1, 0, 0)\n ERC721Bridge(_messenger, _otherBridge)\n {}\n\n /**\n * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n * recipient on this domain.\n *\n * @param _localToken Address of the ERC721 token on this domain.\n * @param _remoteToken Address of the ERC721 token on the other domain.\n * @param _from Address that triggered the bridge on the other domain.\n * @param _to Address to receive the token on this domain.\n * @param _tokenId ID of the token being deposited.\n * @param _extraData Optional data to forward to L1. Data supplied here will not be used to\n * execute any code on L1 and is only emitted as extra data for the\n * convenience of off-chain tooling.\n */\n function finalizeBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n require(_localToken != address(this), \"L2ERC721Bridge: local token cannot be self\");\n\n // Note that supportsInterface makes a callback to the _localToken address which is user\n // provided.\n require(\n ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\n \"L2ERC721Bridge: local token interface is not compliant\"\n );\n\n require(\n _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\n \"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\"\n );\n\n // When a deposit is finalized, we give the NFT with the same tokenId to the account\n // on L2. Note that safeMint makes a callback to the _to address which is user provided.\n IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n\n /**\n * @inheritdoc ERC721Bridge\n */\n function _initiateBridgeERC721(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _tokenId,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal override {\n require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n // Check that the withdrawal is being initiated by the NFT owner\n require(\n _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\n \"Withdrawal is not being initiated by NFT owner\"\n );\n\n // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\n // slither-disable-next-line reentrancy-events\n address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\n require(\n remoteToken == _remoteToken,\n \"L2ERC721Bridge: remote token does not match given value\"\n );\n\n // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\n // usage\n // slither-disable-next-line reentrancy-events\n IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\n\n bytes memory message = abi.encodeWithSelector(\n L1ERC721Bridge.finalizeBridgeERC721.selector,\n remoteToken,\n _localToken,\n _from,\n _to,\n _tokenId,\n _extraData\n );\n\n // Send message to L1 bridge\n // slither-disable-next-line reentrancy-events\n messenger.sendMessage(otherBridge, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\n\n/**\n * @title Semver\n * @notice Semver is a simple contract for managing contract versions.\n */\ncontract Semver {\n /**\n * @notice Contract version number (major).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\n // solhint-disable-next-line var-name-mixedcase\n uint256 private immutable PATCH_VERSION;\n\n /**\n * @param _major Version number (major).\n * @param _minor Version number (minor).\n * @param _patch Version number (patch).\n */\n constructor(\n uint256 _major,\n uint256 _minor,\n uint256 _patch\n ) {\n MAJOR_VERSION = _major;\n MINOR_VERSION = _minor;\n PATCH_VERSION = _patch;\n }\n\n /**\n * @notice Returns the full semver contract version.\n *\n * @return Semver contract version as a string.\n */\n function version() public view returns (string memory) {\n return\n string(\n abi.encodePacked(\n Strings.toString(MAJOR_VERSION),\n \".\",\n Strings.toString(MINOR_VERSION),\n \".\",\n Strings.toString(PATCH_VERSION)\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n PausableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {\n ReentrancyGuardUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * libAddressManager variable used to exist. Must be the first contract in the inheritance\n * tree of the CrossDomainMessenger\n */\ncontract CrossDomainMessengerLegacySpacer {\n /**\n * @custom:legacy\n * @custom:spacer libAddressManager\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n}\n\n/**\n * @custom:upgradeable\n * @title CrossDomainMessenger\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\n * cross-chain messenger contracts. It's designed to be a universal interface that only\n * needs to be extended slightly to provide low-level message passing functionality on each\n * chain it's deployed on. Currently only designed for message passing between two paired\n * chains and does not support one-to-many interactions.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer,\n OwnableUpgradeable,\n PausableUpgradeable,\n ReentrancyGuardUpgradeable\n{\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Constant overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\n\n /**\n * @notice Numerator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\n\n /**\n * @notice Denominator for dynamic overhead added to the base gas for a message.\n */\n uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\n\n /**\n * @notice Extra gas added to base gas for each byte of calldata in a message.\n */\n uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Minimum amount of gas required to relay a message.\n */\n uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\n\n /**\n * @notice Amount of gas held in reserve to guarantee that relay execution completes.\n */\n uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\n\n /**\n * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\n * because performing an SSTORE on a non-zero value is significantly cheaper than on a\n * zero value.\n */\n address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable otherMessenger;\n\n /**\n * @custom:legacy\n * @custom:spacer blockedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_201_0_32;\n\n /**\n * @custom:legacy\n * @custom:spacer relayedMessages\n * @notice Spacer for backwards compatibility.\n */\n mapping(bytes32 => bool) private spacer_202_0_32;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it has successfully been relayed on this chain, and\n * can therefore not be relayed again.\n */\n mapping(bytes32 => bool) public successfulMessages;\n\n /**\n * @notice Address of the sender of the currently executing message on the other chain. If the\n * value of this variable is the default value (0x00000000...dead) then no message is\n * currently being executed. Use the xDomainMessageSender getter which will throw an\n * error if this is the case.\n */\n address internal xDomainMsgSender;\n\n /**\n * @notice Nonce for the next message to be sent, without the message version applied. Use the\n * messageNonce getter which will insert the message version into the nonce to give you\n * the actual nonce to be used for the message.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n * be present in this mapping if it failed to be relayed on this chain at least once.\n * If a message is successfully relayed on the first attempt, then it will only be\n * present within the successfulMessages mapping.\n */\n mapping(bytes32 => bool) public receivedMessages;\n\n /**\n * @notice Reserve extra slots in the storage layout for future upgrades.\n * A gap size of 41 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[42] private __gap;\n\n /**\n * @notice Emitted whenever a message is sent to the other chain.\n *\n * @param target Address of the recipient of the message.\n * @param sender Address of the sender of the message.\n * @param message Message to trigger the recipient address with.\n * @param messageNonce Unique nonce attached to the message.\n * @param gasLimit Minimum gas limit that the message can be executed with.\n */\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n /**\n * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\n * SentMessage event without breaking the ABI of this contract, this is good enough.\n *\n * @param sender Address of the sender of the message.\n * @param value ETH value sent along with the message to the recipient.\n */\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n /**\n * @notice Emitted whenever a message is successfully relayed on this chain.\n *\n * @param msgHash Hash of the message that was relayed.\n */\n event RelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @notice Emitted whenever a message fails to be relayed on this chain.\n *\n * @param msgHash Hash of the message that failed to be relayed.\n */\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n /**\n * @param _otherMessenger Address of the messenger on the paired chain.\n */\n constructor(address _otherMessenger) {\n otherMessenger = _otherMessenger;\n }\n\n /**\n * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\n * security mechanism just in case. Owner should be the same as the upgrade wallet to\n * maintain the security model of the system as a whole.\n */\n function pause() external onlyOwner {\n _pause();\n }\n\n /**\n * @notice Allows the owner of this contract to resume message relaying once paused.\n */\n function unpause() external onlyOwner {\n _unpause();\n }\n\n /**\n * @notice Sends a message to some target address on the other chain. Note that if the call\n * always reverts, then the message will be unrelayable, and any ETH sent will be\n * permanently locked. The same will occur if the target on the other chain is\n * considered unsafe (see the _isUnsafeTarget() function).\n *\n * @param _target Target contract or wallet address.\n * @param _message Message to trigger the target address with.\n * @param _minGasLimit Minimum gas limit that the message can be executed with.\n */\n function sendMessage(\n address _target,\n bytes calldata _message,\n uint32 _minGasLimit\n ) external payable {\n // Triggers a message to the other messenger. Note that the amount of gas provided to the\n // message is the amount of gas requested by the user PLUS the base gas value. We want to\n // guarantee the property that the call to the target contract will always have at least\n // the minimum gas limit specified by the user.\n _sendMessage(\n otherMessenger,\n baseGas(_message, _minGasLimit),\n msg.value,\n abi.encodeWithSelector(\n this.relayMessage.selector,\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _minGasLimit,\n _message\n )\n );\n\n emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\n emit SentMessageExtension1(msg.sender, msg.value);\n\n unchecked {\n ++msgNonce;\n }\n }\n\n /**\n * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\n * be executed via cross-chain call from the other messenger OR if the message was\n * already received once and is currently being replayed.\n *\n * @param _nonce Nonce of the message being relayed.\n * @param _sender Address of the user who sent the message.\n * @param _target Address that the message is targeted at.\n * @param _value ETH value to send with the message.\n * @param _minGasLimit Minimum amount of gas that the message can be executed with.\n * @param _message Message to send to the target.\n */\n function relayMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _minGasLimit,\n bytes calldata _message\n ) external payable nonReentrant whenNotPaused {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n\n // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\n // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\n // to the value or minGasLimit fields, which can create unexpected issues for end-users.\n require(\n version == 1,\n \"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\"\n );\n\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n if (_isOtherMessenger()) {\n // This property should always hold when the message is first submitted (as opposed to\n // being replayed).\n assert(msg.value == _value);\n } else {\n require(\n msg.value == 0,\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n\n require(\n receivedMessages[versionedHash],\n \"CrossDomainMessenger: message cannot be replayed\"\n );\n }\n\n require(\n _isUnsafeTarget(_target) == false,\n \"CrossDomainMessenger: cannot send message to blocked system address\"\n );\n\n require(\n successfulMessages[versionedHash] == false,\n \"CrossDomainMessenger: message has already been relayed\"\n );\n\n require(\n gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\n \"CrossDomainMessenger: insufficient gas to relay message\"\n );\n\n xDomainMsgSender = _sender;\n bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n\n if (success == true) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n receivedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n }\n }\n\n /**\n * @notice Retrieves the address of the contract or wallet that initiated the currently\n * executing message on the other chain. Will throw an error if there is no message\n * currently being executed. Allows the recipient of a call to see who triggered it.\n *\n * @return Address of the sender of the currently executing message on the other chain.\n */\n function xDomainMessageSender() external view returns (address) {\n require(\n xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\n \"CrossDomainMessenger: xDomainMessageSender is not set\"\n );\n\n return xDomainMsgSender;\n }\n\n /**\n * @notice Retrieves the next message nonce. Message version will be added to the upper two\n * bytes of the message nonce. Message version allows us to treat messages as having\n * different structures.\n *\n * @return Nonce of the next message to be sent, with added message version.\n */\n function messageNonce() public view returns (uint256) {\n return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\n }\n\n /**\n * @notice Computes the amount of gas required to guarantee that a given message will be\n * received on the other chain without running out of gas. Guaranteeing that a message\n * will not run out of gas is important because this ensures that a message can always\n * be replayed on the other chain if it fails to execute completely.\n *\n * @param _message Message to compute the amount of required gas for.\n * @param _minGasLimit Minimum desired gas limit when message goes to target.\n *\n * @return Amount of gas required to guarantee message receipt.\n */\n function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\n return\n // Dynamic overhead\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\n // Constant overhead\n MIN_GAS_CONSTANT_OVERHEAD;\n }\n\n /**\n * @notice Intializer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __CrossDomainMessenger_init() internal onlyInitializing {\n xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n __ReentrancyGuard_init_unchained();\n }\n\n /**\n * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @param _to Recipient of the message on the other chain.\n * @param _gasLimit Minimum gas limit the message can be executed with.\n * @param _value Amount of ETH to send with the message.\n * @param _data Message data.\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal virtual;\n\n /**\n * @notice Checks whether the message is coming from the other messenger. Implemented by child\n * contracts because the logic for this depends on the network where the messenger is\n * being deployed.\n *\n * @return Whether the message is coming from the other messenger.\n */\n function _isOtherMessenger() internal view virtual returns (bool);\n\n /**\n * @notice Checks whether a given call target is a system address that could cause the\n * messenger to peform an unsafe action. This is NOT a mechanism for blocking user\n * addresses. This is ONLY used to prevent the execution of messages to specific\n * system addresses that could cause security issues, e.g., having the\n * CrossDomainMessenger send messages to itself.\n *\n * @param _target Address of the contract to check.\n *\n * @return Whether or not the address is an unsafe system address.\n */\n function _isUnsafeTarget(address _target) internal view virtual returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title SafeCall\n * @notice Perform low level safe calls\n */\nlibrary SafeCall {\n /**\n * @notice Perform a low level call without copying any returndata\n *\n * @param _target Address to call\n * @param _gas Amount of gas to pass to the call\n * @param _value Amount of value to pass to the call\n * @param _calldata Calldata to pass to the call\n */\n function call(\n address _target,\n uint256 _gas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n assembly {\n _success := call(\n _gas, // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Encoding } from \"./Encoding.sol\";\n\n/**\n * @title Hashing\n * @notice Hashing handles Optimism's various different hashing schemes.\n */\nlibrary Hashing {\n /**\n * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\n * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\n * system.\n *\n * @param _tx User deposit transaction to hash.\n *\n * @return Hash of the RLP encoded L2 deposit transaction.\n */\n function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return keccak256(Encoding.encodeDepositTransaction(_tx));\n }\n\n /**\n * @notice Computes the deposit transaction's \"source hash\", a value that guarantees the hash\n * of the L2 transaction that corresponds to a deposit is unique and is\n * deterministically generated from L1 transaction data.\n *\n * @param _l1BlockHash Hash of the L1 block where the deposit was included.\n * @param _logIndex The index of the log that created the deposit transaction.\n *\n * @return Hash of the deposit transaction's \"source hash\".\n */\n function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\n internal\n pure\n returns (bytes32)\n {\n bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\n return keccak256(abi.encode(bytes32(0), depositId));\n }\n\n /**\n * @notice Hashes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n if (version == 0) {\n return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Hashing: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes32) {\n return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\n }\n\n /**\n * @notice Hashes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Hashed cross domain message.\n */\n function hashCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes32) {\n return\n keccak256(\n Encoding.encodeCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n )\n );\n }\n\n /**\n * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\n *\n * @param _tx Withdrawal transaction to hash.\n *\n * @return Hashed withdrawal transaction.\n */\n function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\n );\n }\n\n /**\n * @notice Hashes the various elements of an output root proof into an output root hash which\n * can be used to check if the proof is valid.\n *\n * @param _outputRootProof Output root proof which should hash to an output root.\n *\n * @return Hashed output root proof.\n */\n function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\n internal\n pure\n returns (bytes32)\n {\n return\n keccak256(\n abi.encode(\n _outputRootProof.version,\n _outputRootProof.stateRoot,\n _outputRootProof.messagePasserStorageRoot,\n _outputRootProof.latestBlockhash\n )\n );\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Hashing } from \"./Hashing.sol\";\nimport { RLPWriter } from \"./rlp/RLPWriter.sol\";\n\n/**\n * @title Encoding\n * @notice Encoding handles Optimism's various different encoding schemes.\n */\nlibrary Encoding {\n /**\n * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\n * to the L2 system. Useful for searching for a deposit in the L2 system. The\n * transaction is prefixed with 0x7e to identify its EIP-2718 type.\n *\n * @param _tx User deposit transaction to encode.\n *\n * @return RLP encoded L2 deposit transaction.\n */\n function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\n internal\n pure\n returns (bytes memory)\n {\n bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\n bytes[] memory raw = new bytes[](8);\n raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\n raw[1] = RLPWriter.writeAddress(_tx.from);\n raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\"\") : RLPWriter.writeAddress(_tx.to);\n raw[3] = RLPWriter.writeUint(_tx.mint);\n raw[4] = RLPWriter.writeUint(_tx.value);\n raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\n raw[6] = RLPWriter.writeBool(false);\n raw[7] = RLPWriter.writeBytes(_tx.data);\n return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\n }\n\n /**\n * @notice Encodes the cross domain message based on the version that is encoded into the\n * message nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n (, uint16 version) = decodeVersionedNonce(_nonce);\n if (version == 0) {\n return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\n } else if (version == 1) {\n return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n } else {\n revert(\"Encoding: unknown cross domain message version\");\n }\n }\n\n /**\n * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\n *\n * @param _target Address of the target of the message.\n * @param _sender Address of the sender of the message.\n * @param _data Data to send with the message.\n * @param _nonce Message nonce.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV0(\n address _target,\n address _sender,\n bytes memory _data,\n uint256 _nonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _data,\n _nonce\n );\n }\n\n /**\n * @notice Encodes a cross domain message based on the V1 (current) encoding.\n *\n * @param _nonce Message nonce.\n * @param _sender Address of the sender of the message.\n * @param _target Address of the target of the message.\n * @param _value ETH value to send to the target.\n * @param _gasLimit Gas limit to use for the message.\n * @param _data Data to send with the message.\n *\n * @return Encoded cross domain message.\n */\n function encodeCrossDomainMessageV1(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(uint256,address,address,uint256,uint256,bytes)\",\n _nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n }\n\n /**\n * @notice Adds a version number into the first two bytes of a message nonce.\n *\n * @param _nonce Message nonce to encode into.\n * @param _version Version number to encode into the message nonce.\n *\n * @return Message nonce with version encoded into the first two bytes.\n */\n function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\n uint256 nonce;\n assembly {\n nonce := or(shl(240, _version), _nonce)\n }\n return nonce;\n }\n\n /**\n * @notice Pulls the version out of a version-encoded nonce.\n *\n * @param _nonce Message nonce with version encoded into the first two bytes.\n *\n * @return Nonce without encoded version.\n * @return Version of the message.\n */\n function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\n uint240 nonce;\n uint16 version;\n assembly {\n nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n version := shr(240, _nonce)\n }\n return (nonce, version);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Types\n * @notice Contains various types used throughout the Optimism contract system.\n */\nlibrary Types {\n /**\n * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\n * timestamp that the output root is posted. This timestamp is used to verify that the\n * finalization period has passed since the output root was submitted.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint256 timestamp;\n }\n\n /**\n * @notice Struct representing the elements that are hashed together to generate an output root\n * which itself represents a snapshot of the L2 state.\n */\n struct OutputRootProof {\n bytes32 version;\n bytes32 stateRoot;\n bytes32 messagePasserStorageRoot;\n bytes32 latestBlockhash;\n }\n\n /**\n * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\n * user (as opposed to a system deposit transaction generated by the system).\n */\n struct UserDepositTransaction {\n address from;\n address to;\n bool isCreation;\n uint256 value;\n uint256 mint;\n uint64 gasLimit;\n bytes data;\n bytes32 l1BlockHash;\n uint256 logIndex;\n }\n\n /**\n * @notice Struct representing a withdrawal transaction.\n */\n struct WithdrawalTransaction {\n uint256 nonce;\n address sender;\n address target;\n uint256 value;\n uint256 gasLimit;\n bytes data;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\n * @title RLPWriter\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\n * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\n * modifications to improve legibility.\n */\nlibrary RLPWriter {\n /**\n * @notice RLP encodes a byte string.\n *\n * @param _in The byte string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_in.length == 1 && uint8(_in[0]) < 128) {\n encoded = _in;\n } else {\n encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\n }\n\n return encoded;\n }\n\n /**\n * @notice RLP encodes a list of RLP encoded byte byte strings.\n *\n * @param _in The list of RLP encoded byte strings.\n *\n * @return The RLP encoded list of items in bytes.\n */\n function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\n bytes memory list = _flatten(_in);\n return abi.encodePacked(_writeLength(list.length, 192), list);\n }\n\n /**\n * @notice RLP encodes a string.\n *\n * @param _in The string to encode.\n *\n * @return The RLP encoded string in bytes.\n */\n function writeString(string memory _in) internal pure returns (bytes memory) {\n return writeBytes(bytes(_in));\n }\n\n /**\n * @notice RLP encodes an address.\n *\n * @param _in The address to encode.\n *\n * @return The RLP encoded address in bytes.\n */\n function writeAddress(address _in) internal pure returns (bytes memory) {\n return writeBytes(abi.encodePacked(_in));\n }\n\n /**\n * @notice RLP encodes a uint.\n *\n * @param _in The uint256 to encode.\n *\n * @return The RLP encoded uint256 in bytes.\n */\n function writeUint(uint256 _in) internal pure returns (bytes memory) {\n return writeBytes(_toBinary(_in));\n }\n\n /**\n * @notice RLP encodes a bool.\n *\n * @param _in The bool to encode.\n *\n * @return The RLP encoded bool in bytes.\n */\n function writeBool(bool _in) internal pure returns (bytes memory) {\n bytes memory encoded = new bytes(1);\n encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n return encoded;\n }\n\n /**\n * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\n *\n * @param _len The length of the string or the payload.\n * @param _offset 128 if item is string, 192 if item is list.\n *\n * @return RLP encoded bytes.\n */\n function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\n bytes memory encoded;\n\n if (_len < 56) {\n encoded = new bytes(1);\n encoded[0] = bytes1(uint8(_len) + uint8(_offset));\n } else {\n uint256 lenLen;\n uint256 i = 1;\n while (_len / i != 0) {\n lenLen++;\n i *= 256;\n }\n\n encoded = new bytes(lenLen + 1);\n encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\n for (i = 1; i <= lenLen; i++) {\n encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\n }\n }\n\n return encoded;\n }\n\n /**\n * @notice Encode integer in big endian binary form with no leading zeroes.\n *\n * @param _x The integer to encode.\n *\n * @return RLP encoded bytes.\n */\n function _toBinary(uint256 _x) private pure returns (bytes memory) {\n bytes memory b = abi.encodePacked(_x);\n\n uint256 i = 0;\n for (; i < 32; i++) {\n if (b[i] != 0) {\n break;\n }\n }\n\n bytes memory res = new bytes(32 - i);\n for (uint256 j = 0; j < res.length; j++) {\n res[j] = b[i++];\n }\n\n return res;\n }\n\n /**\n * @custom:attribution https://github.com/Arachnid/solidity-stringutils\n * @notice Copies a piece of memory to another location.\n *\n * @param _dest Destination location.\n * @param _src Source location.\n * @param _len Length of memory to copy.\n */\n function _memcpy(\n uint256 _dest,\n uint256 _src,\n uint256 _len\n ) private pure {\n uint256 dest = _dest;\n uint256 src = _src;\n uint256 len = _len;\n\n for (; len >= 32; len -= 32) {\n assembly {\n mstore(dest, mload(src))\n }\n dest += 32;\n src += 32;\n }\n\n uint256 mask;\n unchecked {\n mask = 256**(32 - len) - 1;\n }\n assembly {\n let srcpart := and(mload(src), not(mask))\n let destpart := and(mload(dest), mask)\n mstore(dest, or(destpart, srcpart))\n }\n }\n\n /**\n * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\n * @notice Flattens a list of byte strings into one byte string.\n *\n * @param _list List of byte strings to flatten.\n *\n * @return The flattened byte string.\n */\n function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\n if (_list.length == 0) {\n return new bytes(0);\n }\n\n uint256 len;\n uint256 i = 0;\n for (; i < _list.length; i++) {\n len += _list[i].length;\n }\n\n bytes memory flattened = new bytes(len);\n uint256 flattenedPtr;\n assembly {\n flattenedPtr := add(flattened, 0x20)\n }\n\n for (i = 0; i < _list.length; i++) {\n bytes memory item = _list[i];\n\n uint256 listPtr;\n assembly {\n listPtr := add(item, 0x20)\n }\n\n _memcpy(flattenedPtr, listPtr, item.length);\n flattenedPtr += _list[i].length;\n }\n\n return flattened;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" + }, + "contracts/universal/op-erc721/IOptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n IERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\";\n\n/**\n * @title IOptimismMintableERC721\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\n * Tokens that follow this standard can be easily transferred across the ERC721 bridge.\n */\ninterface IOptimismMintableERC721 is IERC721Enumerable {\n /**\n * @notice Emitted when a token is minted.\n *\n * @param account Address of the account the token was minted to.\n * @param tokenId Token ID of the minted token.\n */\n event Mint(address indexed account, uint256 tokenId);\n\n /**\n * @notice Emitted when a token is burned.\n *\n * @param account Address of the account the token was burned from.\n * @param tokenId Token ID of the burned token.\n */\n event Burn(address indexed account, uint256 tokenId);\n\n /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function remoteChainId() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function remoteToken() external view returns (address);\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n function bridge() external view returns (address);\n\n /**\n * @notice Mints some token ID for a user, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * @param _to Address of the user to mint the token for.\n * @param _tokenId Token ID to mint.\n */\n function safeMint(address _to, uint256 _tokenId) external;\n\n /**\n * @notice Burns a token ID from a user.\n *\n * @param _from Address of the user to burn the token from.\n * @param _tokenId Token ID to burn.\n */\n function burn(address _from, uint256 _tokenId) external;\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n /**\n * @dev Returns the total amount of tokens stored by the contract.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n /**\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n * Use along with {totalSupply} to enumerate all tokens.\n */\n function tokenByIndex(uint256 index) external view returns (uint256);\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismMintableERC721 } from \"./OptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC721Factory\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\n */\ncontract OptimismMintableERC721Factory is Semver {\n /**\n * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\n *\n * @param localToken Address of the token on the this domain.\n * @param remoteToken Address of the token on the remote domain.\n * @param deployer Address of the initiator of the deployment\n */\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @notice Address of the ERC721 bridge on this network.\n */\n address public immutable bridge;\n\n /**\n * @notice Chain ID for the remote network.\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 0, 0) {\n require(\n _bridge != address(0),\n \"OptimismMintableERC721Factory: bridge cannot be address(0)\"\n );\n require(\n _remoteChainId != 0,\n \"OptimismMintableERC721Factory: remote chain id cannot be zero\"\n );\n\n bridge = _bridge;\n remoteChainId = _remoteChainId;\n }\n\n /**\n * @notice Creates an instance of the standard ERC721.\n *\n * @param _remoteToken Address of the corresponding token on the other domain.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n function createOptimismMintableERC721(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721Factory: L1 token address cannot be address(0)\"\n );\n\n address localToken = address(\n new OptimismMintableERC721(bridge, remoteChainId, _remoteToken, _name, _symbol)\n );\n\n isOptimismMintableERC721[localToken] = true;\n emit OptimismMintableERC721Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" + }, + "contracts/universal/op-erc721/OptimismMintableERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n ERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { IOptimismMintableERC721 } from \"./IOptimismMintableERC721.sol\";\n\n/**\n * @title OptimismMintableERC721\n * @notice This contract is the remote representation for some token that lives on another network,\n * typically an Optimism representation of an Ethereum-based token. Standard reference\n * implementation that can be extended or modified according to your needs.\n */\ncontract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable remoteChainId;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable remoteToken;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable bridge;\n\n /**\n * @notice Base token URI for this token.\n */\n string public baseTokenURI;\n\n /**\n * @param _bridge Address of the bridge on this network.\n * @param _remoteChainId Chain ID where the remote token is deployed.\n * @param _remoteToken Address of the corresponding token on the other network.\n * @param _name ERC721 name.\n * @param _symbol ERC721 symbol.\n */\n constructor(\n address _bridge,\n uint256 _remoteChainId,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC721(_name, _symbol) {\n require(_bridge != address(0), \"OptimismMintableERC721: bridge cannot be address(0)\");\n require(_remoteChainId != 0, \"OptimismMintableERC721: remote chain id cannot be zero\");\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC721: remote token cannot be address(0)\"\n );\n\n remoteChainId = _remoteChainId;\n remoteToken = _remoteToken;\n bridge = _bridge;\n\n // Creates a base URI in the format specified by EIP-681:\n // https://eips.ethereum.org/EIPS/eip-681\n baseTokenURI = string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(_remoteToken), 20),\n \"@\",\n Strings.toString(_remoteChainId),\n \"/tokenURI?uint256=\"\n )\n );\n }\n\n /**\n * @notice Modifier that prevents callers other than the bridge from calling the function.\n */\n modifier onlyBridge() {\n require(msg.sender == bridge, \"OptimismMintableERC721: only bridge can call this function\");\n _;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {\n _safeMint(_to, _tokenId);\n\n emit Mint(_to, _tokenId);\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function burn(address _from, uint256 _tokenId) external virtual onlyBridge {\n _burn(_tokenId);\n\n emit Burn(_from, _tokenId);\n }\n\n /**\n * @notice Checks if a given interface ID is supported by this contract.\n *\n * @param _interfaceId The interface ID to check.\n *\n * @return True if the interface ID is supported, false otherwise.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n override(ERC721Enumerable, IERC165)\n returns (bool)\n {\n bytes4 iface1 = type(IERC165).interfaceId;\n bytes4 iface2 = type(IOptimismMintableERC721).interfaceId;\n return\n _interfaceId == iface1 ||\n _interfaceId == iface2 ||\n super.supportsInterface(_interfaceId);\n }\n\n /**\n * @notice Returns the base token URI.\n *\n * @return Base token URI.\n */\n function _baseURI() internal view virtual override returns (string memory) {\n return baseTokenURI;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721.sol\";\nimport \"./IERC721Enumerable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\n // Mapping from owner to list of owned token IDs\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n // Mapping from token ID to index of the owner tokens list\n mapping(uint256 => uint256) private _ownedTokensIndex;\n\n // Array with all token ids, used for enumeration\n uint256[] private _allTokens;\n\n // Mapping from token id to position in the allTokens array\n mapping(uint256 => uint256) private _allTokensIndex;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721.balanceOf(owner), \"ERC721Enumerable: owner index out of bounds\");\n return _ownedTokens[owner][index];\n }\n\n /**\n * @dev See {IERC721Enumerable-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _allTokens.length;\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenByIndex}.\n */\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721Enumerable.totalSupply(), \"ERC721Enumerable: global index out of bounds\");\n return _allTokens[index];\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, tokenId);\n\n if (from == address(0)) {\n _addTokenToAllTokensEnumeration(tokenId);\n } else if (from != to) {\n _removeTokenFromOwnerEnumeration(from, tokenId);\n }\n if (to == address(0)) {\n _removeTokenFromAllTokensEnumeration(tokenId);\n } else if (to != from) {\n _addTokenToOwnerEnumeration(to, tokenId);\n }\n }\n\n /**\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\n * @param to address representing the new owner of the given token ID\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n */\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n uint256 length = ERC721.balanceOf(to);\n _ownedTokens[to][length] = tokenId;\n _ownedTokensIndex[tokenId] = length;\n }\n\n /**\n * @dev Private function to add a token to this extension's token tracking data structures.\n * @param tokenId uint256 ID of the token to be added to the tokens list\n */\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n _allTokensIndex[tokenId] = _allTokens.length;\n _allTokens.push(tokenId);\n }\n\n /**\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n * @param from address representing the previous owner of the given token ID\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n */\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary\n if (tokenIndex != lastTokenIndex) {\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\n\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n }\n\n // This also deletes the contents at the last position of the array\n delete _ownedTokensIndex[tokenId];\n delete _ownedTokens[from][lastTokenIndex];\n }\n\n /**\n * @dev Private function to remove a token from this extension's token tracking data structures.\n * This has O(1) time complexity, but alters the order of the _allTokens array.\n * @param tokenId uint256 ID of the token to be removed from the tokens list\n */\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = _allTokens.length - 1;\n uint256 tokenIndex = _allTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n uint256 lastTokenId = _allTokens[lastTokenIndex];\n\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n // This also deletes the contents at the last position of the array\n delete _allTokensIndex[tokenId];\n _allTokens.pop();\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: balance query for the zero address\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _owners[tokenId];\n require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not owner nor approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n _safeTransfer(from, to, tokenId, _data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _owners[tokenId] != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, _data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId);\n\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId);\n\n // Clear approvals\n _approve(address(0), tokenId);\n\n _balances[owner] -= 1;\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId);\n\n // Clear approvals from the previous owner\n _approve(address(0), tokenId);\n\n _balances[from] -= 1;\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits a {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/AddressManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:legacy\n * @title AddressManager\n * @notice AddressManager is a legacy contract that was used in the old version of the Optimism\n * system to manage a registry of string names to addresses. We now use a more standard\n * proxy system instead, but this contract is still necessary for backwards compatibility\n * with several older contracts.\n */\ncontract AddressManager is Ownable {\n /**\n * @notice Mapping of the hashes of string names to addresses.\n */\n mapping(bytes32 => address) private addresses;\n\n /**\n * @notice Emitted when an address is modified in the registry.\n *\n * @param name String name being set in the registry.\n * @param newAddress Address set for the given name.\n * @param oldAddress Address that was previously set for the given name.\n */\n event AddressSet(string indexed name, address newAddress, address oldAddress);\n\n /**\n * @notice Changes the address associated with a particular name.\n *\n * @param _name String name to associate an address with.\n * @param _address Address to associate with the name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n bytes32 nameHash = _getNameHash(_name);\n address oldAddress = addresses[nameHash];\n addresses[nameHash] = _address;\n\n emit AddressSet(_name, _address, oldAddress);\n }\n\n /**\n * @notice Retrieves the address associated with a given name.\n *\n * @param _name Name to retrieve an address for.\n *\n * @return Address associated with the given name.\n */\n function getAddress(string memory _name) external view returns (address) {\n return addresses[_getNameHash(_name)];\n }\n\n /**\n * @notice Computes the hash of a name.\n *\n * @param _name Name to compute a hash for.\n *\n * @return Hash of the given name.\n */\n function _getNameHash(string memory _name) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(_name));\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\nimport { Proxy } from \"./Proxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\n\n/**\n * @title IStaticERC1967Proxy\n * @notice IStaticERC1967Proxy is a static version of the ERC1967 proxy interface.\n */\ninterface IStaticERC1967Proxy {\n function implementation() external view returns (address);\n\n function admin() external view returns (address);\n}\n\n/**\n * @title IStaticL1ChugSplashProxy\n * @notice IStaticL1ChugSplashProxy is a static version of the ChugSplash proxy interface.\n */\ninterface IStaticL1ChugSplashProxy {\n function getImplementation() external view returns (address);\n\n function getOwner() external view returns (address);\n}\n\n/**\n * @title ProxyAdmin\n * @notice This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy,\n * based on the OpenZeppelin implementation. It has backwards compatibility logic to work\n * with the various types of proxies that have been deployed by Optimism in the past.\n */\ncontract ProxyAdmin is Owned {\n /**\n * @notice The proxy types that the ProxyAdmin can manage.\n *\n * @custom:value ERC1967 Represents an ERC1967 compliant transparent proxy interface.\n * @custom:value CHUGSPLASH Represents the Chugsplash proxy interface (legacy).\n * @custom:value RESOLVED Represents the ResolvedDelegate proxy (legacy).\n */\n enum ProxyType {\n ERC1967,\n CHUGSPLASH,\n RESOLVED\n }\n\n /**\n * @custom:legacy\n * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\n * @custom:legacy\n * @notice A reverse mapping of addresses to names held in the AddressManager. This must be\n * manually kept up to date with changes in the AddressManager for this contract\n * to be able to work as an admin for the ResolvedDelegateProxy type.\n */\n mapping(address => string) public implementationName;\n\n /**\n * @custom:legacy\n * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @custom:legacy\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading = false;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * @notice Sets the proxy type for a given address. Only required for non-standard (legacy)\n * proxy types.\n *\n * @param _address Address of the proxy.\n * @param _type Type of the proxy.\n */\n function setProxyType(address _address, ProxyType _type) external onlyOwner {\n proxyType[_address] = _type;\n }\n\n /**\n * @notice Sets the implementation name for a given address. Only required for\n * ResolvedDelegateProxy type proxies that have an implementation name.\n *\n * @param _address Address of the ResolvedDelegateProxy.\n * @param _name Name of the implementation for the proxy.\n */\n function setImplementationName(address _address, string memory _name) external onlyOwner {\n implementationName[_address] = _name;\n }\n\n /**\n * @notice Set the address of the AddressManager. This is required to manage legacy\n * ResolvedDelegateProxy type proxy contracts.\n *\n * @param _address Address of the AddressManager.\n */\n function setAddressManager(AddressManager _address) external onlyOwner {\n addressManager = _address;\n }\n\n /**\n * @custom:legacy\n * @notice Set an address in the address manager. Since only the owner of the AddressManager\n * can directly modify addresses and the ProxyAdmin will own the AddressManager, this\n * gives the owner of the ProxyAdmin the ability to modify addresses directly.\n *\n * @param _name Name to set within the AddressManager.\n * @param _address Address to attach to the given name.\n */\n function setAddress(string memory _name, address _address) external onlyOwner {\n addressManager.setAddress(_name, _address);\n }\n\n /**\n * @custom:legacy\n * @notice Set the upgrading status for the Chugsplash proxy type.\n *\n * @param _upgrading Whether or not the system is upgrading.\n */\n function setUpgrading(bool _upgrading) external onlyOwner {\n upgrading = _upgrading;\n }\n\n /**\n * @notice Updates the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to update.\n * @param _newAdmin Address of the new proxy admin.\n */\n function changeProxyAdmin(address payable _proxy, address _newAdmin) external onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).changeAdmin(_newAdmin);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setOwner(_newAdmin);\n } else if (ptype == ProxyType.RESOLVED) {\n addressManager.transferOwnership(_newAdmin);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract and delegatecalls the new implementation\n * with some given data. Useful for atomic upgrade-and-initialize calls.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n * @param _data Data to trigger the new implementation with.\n */\n function upgradeAndCall(\n address payable _proxy,\n address _implementation,\n bytes memory _data\n ) external payable onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeToAndCall{ value: msg.value }(_implementation, _data);\n } else {\n // reverts if proxy type is unknown\n upgrade(_proxy, _implementation);\n (bool success, ) = _proxy.call{ value: msg.value }(_data);\n require(success, \"ProxyAdmin: call to proxy after upgrade failed\");\n }\n }\n\n /**\n * @custom:legacy\n * @notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\n *\n * @return Whether or not there is an upgrade going on. May not actually tell you whether an\n * upgrade is going on, since we don't currently plan to use this variable for anything\n * other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\n */\n function isUpgrading() external view returns (bool) {\n return upgrading;\n }\n\n /**\n * @notice Returns the implementation of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the implementation of.\n *\n * @return Address of the implementation of the proxy.\n */\n function getProxyImplementation(address _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).implementation();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getImplementation();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.getAddress(implementationName[_proxy]);\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Returns the admin of the given proxy address.\n *\n * @param _proxy Address of the proxy to get the admin of.\n *\n * @return Address of the admin of the proxy.\n */\n function getProxyAdmin(address payable _proxy) external view returns (address) {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n return IStaticERC1967Proxy(_proxy).admin();\n } else if (ptype == ProxyType.CHUGSPLASH) {\n return IStaticL1ChugSplashProxy(_proxy).getOwner();\n } else if (ptype == ProxyType.RESOLVED) {\n return addressManager.owner();\n } else {\n revert(\"ProxyAdmin: unknown proxy type\");\n }\n }\n\n /**\n * @notice Changes a proxy's implementation contract.\n *\n * @param _proxy Address of the proxy to upgrade.\n * @param _implementation Address of the new implementation address.\n */\n function upgrade(address payable _proxy, address _implementation) public onlyOwner {\n ProxyType ptype = proxyType[_proxy];\n if (ptype == ProxyType.ERC1967) {\n Proxy(_proxy).upgradeTo(_implementation);\n } else if (ptype == ProxyType.CHUGSPLASH) {\n L1ChugSplashProxy(_proxy).setStorage(\n // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,\n bytes32(uint256(uint160(_implementation)))\n );\n } else if (ptype == ProxyType.RESOLVED) {\n string memory name = implementationName[_proxy];\n addressManager.setAddress(name, _implementation);\n } else {\n // It should not be possible to retrieve a ProxyType value which is not matched by\n // one of the previous conditions.\n assert(false);\n }\n }\n}\n" + }, + "@rari-capital/solmate/src/auth/Owned.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol)\nabstract contract Owned {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event OwnerUpdated(address indexed user, address indexed newOwner);\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP STORAGE\n //////////////////////////////////////////////////////////////*/\n\n address public owner;\n\n modifier onlyOwner() virtual {\n require(msg.sender == owner, \"UNAUTHORIZED\");\n\n _;\n }\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(address _owner) {\n owner = _owner;\n\n emit OwnerUpdated(address(0), _owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function setOwner(address newOwner) public virtual onlyOwner {\n owner = newOwner;\n\n emit OwnerUpdated(msg.sender, newOwner);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Proxy\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\n * if the caller is address(0), meaning that the call originated from an off-chain\n * simulation.\n */\ncontract Proxy {\n /**\n * @notice The storage slot that holds the address of the implementation.\n * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice The storage slot that holds the address of the owner.\n * bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice An event that is emitted each time the implementation is changed. This event is part\n * of the EIP-1967 specification.\n *\n * @param implementation The address of the implementation contract\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @notice An event that is emitted each time the owner is upgraded. This event is part of the\n * EIP-1967 specification.\n *\n * @param previousAdmin The previous owner of the contract\n * @param newAdmin The new owner of the contract\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @notice A modifier that reverts if not called by the owner or by address(0) to allow\n * eth_call to interact with this proxy without needing to use low-level storage\n * inspection. We assume that nobody is able to trigger calls from address(0) during\n * normal EVM execution.\n */\n modifier proxyCallIfNotAdmin() {\n if (msg.sender == _getAdmin() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @notice Sets the initial admin during contract deployment. Admin address is stored at the\n * EIP-1967 admin storage slot so that accidental storage collision with the\n * implementation is not possible.\n *\n * @param _admin Address of the initial contract admin. Admin as the ability to access the\n * transparent proxy interface.\n */\n constructor(address _admin) {\n _changeAdmin(_admin);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Set the implementation contract address. The code at the given address will execute\n * when this contract is called.\n *\n * @param _implementation Address of the implementation contract.\n */\n function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\n _setImplementation(_implementation);\n }\n\n /**\n * @notice Set the implementation and call a function in a single transaction. Useful to ensure\n * atomic execution of initialization-based upgrades.\n *\n * @param _implementation Address of the implementation contract.\n * @param _data Calldata to delegatecall the new implementation with.\n */\n function upgradeToAndCall(address _implementation, bytes calldata _data)\n external\n payable\n proxyCallIfNotAdmin\n returns (bytes memory)\n {\n _setImplementation(_implementation);\n (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\n require(success, \"Proxy: delegatecall to new implementation contract failed\");\n return returndata;\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _admin New owner of the proxy contract.\n */\n function changeAdmin(address _admin) external proxyCallIfNotAdmin {\n _changeAdmin(_admin);\n }\n\n /**\n * @notice Gets the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function admin() external proxyCallIfNotAdmin returns (address) {\n return _getAdmin();\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function implementation() external proxyCallIfNotAdmin returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n emit Upgraded(_implementation);\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _admin New owner of the proxy contract.\n */\n function _changeAdmin(address _admin) internal {\n address previous = _getAdmin();\n assembly {\n sstore(OWNER_KEY, _admin)\n }\n emit AdminChanged(previous, _admin);\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal {\n address impl = _getImplementation();\n require(impl != address(0), \"Proxy: implementation not initialized\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address impl;\n assembly {\n impl := sload(IMPLEMENTATION_KEY)\n }\n return impl;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getAdmin() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/contracts/legacy/L1ChugSplashProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title IL1ChugSplashDeployer\n */\ninterface IL1ChugSplashDeployer {\n function isUpgrading() external view returns (bool);\n}\n\n/**\n * @custom:legacy\n * @title L1ChugSplashProxy\n * @notice Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added\n * functions `setCode` and `setStorage` for changing the code or storage of the contract.\n *\n * Note for future developers: do NOT make anything in this contract 'public' unless you\n * know what you're doing. Anything public can potentially have a function signature that\n * conflicts with a signature attached to the implementation contract. Public functions\n * SHOULD always have the `proxyCallIfNotOwner` modifier unless there's some *really* good\n * reason not to have that modifier. And there almost certainly is not a good reason to not\n * have that modifier. Beware!\n */\ncontract L1ChugSplashProxy {\n /**\n * @notice \"Magic\" prefix. When prepended to some arbitrary bytecode and used to create a\n * contract, the appended bytecode will be deployed as given.\n */\n bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n */\n bytes32 internal constant IMPLEMENTATION_KEY =\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @notice bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n */\n bytes32 internal constant OWNER_KEY =\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @notice Blocks a function from being called when the parent signals that the system should\n * be paused via an isUpgrading function.\n */\n modifier onlyWhenNotPaused() {\n address owner = _getOwner();\n\n // We do a low-level call because there's no guarantee that the owner actually *is* an\n // L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and\n // it turns out that it isn't the right type of contract.\n (bool success, bytes memory returndata) = owner.staticcall(\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector)\n );\n\n // If the call was unsuccessful then we assume that there's no \"isUpgrading\" method and we\n // can just continue as normal. We also expect that the return value is exactly 32 bytes\n // long. If this isn't the case then we can safely ignore the result.\n if (success && returndata.length == 32) {\n // Although the expected value is a *boolean*, it's safer to decode as a uint256 in the\n // case that the isUpgrading function returned something other than 0 or 1. But we only\n // really care about the case where this value is 0 (= false).\n uint256 ret = abi.decode(returndata, (uint256));\n require(ret == 0, \"L1ChugSplashProxy: system is currently being upgraded\");\n }\n\n _;\n }\n\n /**\n * @notice Makes a proxy call instead of triggering the given function when the caller is\n * either the owner or the zero address. Caller can only ever be the zero address if\n * this function is being called off-chain via eth_call, which is totally fine and can\n * be convenient for client-side tooling. Avoids situations where the proxy and\n * implementation share a sighash and the proxy function ends up being called instead\n * of the implementation one.\n *\n * Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If\n * there's a way for someone to send a transaction with msg.sender == address(0) in any\n * real context then we have much bigger problems. Primary reason to include this\n * additional allowed sender is because the owner address can be changed dynamically\n * and we do not want clients to have to keep track of the current owner in order to\n * make an eth_call that doesn't trigger the proxied contract.\n */\n // slither-disable-next-line incorrect-modifier\n modifier proxyCallIfNotOwner() {\n if (msg.sender == _getOwner() || msg.sender == address(0)) {\n _;\n } else {\n // This WILL halt the call frame on completion.\n _doProxyCall();\n }\n }\n\n /**\n * @param _owner Address of the initial contract owner.\n */\n constructor(address _owner) {\n _setOwner(_owner);\n }\n\n // slither-disable-next-line locked-ether\n receive() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n // slither-disable-next-line locked-ether\n fallback() external payable {\n // Proxy call by default.\n _doProxyCall();\n }\n\n /**\n * @notice Sets the code that should be running behind this proxy.\n *\n * Note: This scheme is a bit different from the standard proxy scheme where one would\n * typically deploy the code separately and then set the implementation address. We're\n * doing it this way because it gives us a lot more freedom on the client side. Can\n * only be triggered by the contract owner.\n *\n * @param _code New contract code to run inside this contract.\n */\n function setCode(bytes memory _code) external proxyCallIfNotOwner {\n // Get the code hash of the current implementation.\n address implementation = _getImplementation();\n\n // If the code hash matches the new implementation then we return early.\n if (keccak256(_code) == _getAccountCodeHash(implementation)) {\n return;\n }\n\n // Create the deploycode by appending the magic prefix.\n bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code);\n\n // Deploy the code and set the new implementation address.\n address newImplementation;\n assembly {\n newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode))\n }\n\n // Check that the code was actually deployed correctly. I'm not sure if you can ever\n // actually fail this check. Should only happen if the contract creation from above runs\n // out of gas but this parent execution thread does NOT run out of gas. Seems like we\n // should be doing this check anyway though.\n require(\n _getAccountCodeHash(newImplementation) == keccak256(_code),\n \"L1ChugSplashProxy: code was not correctly deployed\"\n );\n\n _setImplementation(newImplementation);\n }\n\n /**\n * @notice Modifies some storage slot within the proxy contract. Gives us a lot of power to\n * perform upgrades in a more transparent way. Only callable by the owner.\n *\n * @param _key Storage key to modify.\n * @param _value New value for the storage key.\n */\n function setStorage(bytes32 _key, bytes32 _value) external proxyCallIfNotOwner {\n assembly {\n sstore(_key, _value)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract. Only callable by the owner.\n *\n * @param _owner New owner of the proxy contract.\n */\n function setOwner(address _owner) external proxyCallIfNotOwner {\n _setOwner(_owner);\n }\n\n /**\n * @notice Queries the owner of the proxy contract. Can only be called by the owner OR by\n * making an eth_call and setting the \"from\" address to address(0).\n *\n * @return Owner address.\n */\n function getOwner() external proxyCallIfNotOwner returns (address) {\n return _getOwner();\n }\n\n /**\n * @notice Queries the implementation address. Can only be called by the owner OR by making an\n * eth_call and setting the \"from\" address to address(0).\n *\n * @return Implementation address.\n */\n function getImplementation() external proxyCallIfNotOwner returns (address) {\n return _getImplementation();\n }\n\n /**\n * @notice Sets the implementation address.\n *\n * @param _implementation New implementation address.\n */\n function _setImplementation(address _implementation) internal {\n assembly {\n sstore(IMPLEMENTATION_KEY, _implementation)\n }\n }\n\n /**\n * @notice Changes the owner of the proxy contract.\n *\n * @param _owner New owner of the proxy contract.\n */\n function _setOwner(address _owner) internal {\n assembly {\n sstore(OWNER_KEY, _owner)\n }\n }\n\n /**\n * @notice Performs the proxy call via a delegatecall.\n */\n function _doProxyCall() internal onlyWhenNotPaused {\n address implementation = _getImplementation();\n\n require(implementation != address(0), \"L1ChugSplashProxy: implementation is not set yet\");\n\n assembly {\n // Copy calldata into memory at 0x0....calldatasize.\n calldatacopy(0x0, 0x0, calldatasize())\n\n // Perform the delegatecall, make sure to pass all available gas.\n let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)\n\n // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n // overwrite the calldata that we just copied into memory but that doesn't really\n // matter because we'll be returning in a second anyway.\n returndatacopy(0x0, 0x0, returndatasize())\n\n // Success == 0 means a revert. We'll revert too and pass the data up.\n if iszero(success) {\n revert(0x0, returndatasize())\n }\n\n // Otherwise we'll just return and pass the data up.\n return(0x0, returndatasize())\n }\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function _getImplementation() internal view returns (address) {\n address implementation;\n assembly {\n implementation := sload(IMPLEMENTATION_KEY)\n }\n return implementation;\n }\n\n /**\n * @notice Queries the owner of the proxy contract.\n *\n * @return Owner address.\n */\n function _getOwner() internal view returns (address) {\n address owner;\n assembly {\n owner := sload(OWNER_KEY)\n }\n return owner;\n }\n\n /**\n * @notice Gets the code hash for a given account.\n *\n * @param _account Address of the account to get a code hash for.\n *\n * @return Code hash for the account.\n */\n function _getAccountCodeHash(address _account) internal view returns (bytes32) {\n bytes32 codeHash;\n assembly {\n codeHash := extcodehash(_account)\n }\n return codeHash;\n }\n}\n" + }, + "contracts/testing/helpers/ExternalContractCompiler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ProxyAdmin } from \"@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol\";\nimport { Proxy } from \"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\";\n\n/**\n * Just exists so we can compile external contracts.\n */\ncontract ExternalContractCompiler {\n\n}\n" + }, + "contracts/testing/helpers/TestERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\n\ncontract TestERC721 is ERC721 {\n constructor() ERC721(\"TEST\", \"TST\") {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n\n function tokenURI(uint256) public pure virtual override returns (string memory) {}\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 indexed id);\n\n event Approval(address indexed owner, address indexed spender, uint256 indexed id);\n\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE/LOGIC\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n function tokenURI(uint256 id) public view virtual returns (string memory);\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) internal _ownerOf;\n\n mapping(address => uint256) internal _balanceOf;\n\n function ownerOf(uint256 id) public view virtual returns (address owner) {\n require((owner = _ownerOf[id]) != address(0), \"NOT_MINTED\");\n }\n\n function balanceOf(address owner) public view virtual returns (uint256) {\n require(owner != address(0), \"ZERO_ADDRESS\");\n\n return _balanceOf[owner];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint256 => address) public getApproved;\n\n mapping(address => mapping(address => bool)) public isApprovedForAll;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(string memory _name, string memory _symbol) {\n name = _name;\n symbol = _symbol;\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 id) public virtual {\n address owner = _ownerOf[id];\n\n require(msg.sender == owner || isApprovedForAll[owner][msg.sender], \"NOT_AUTHORIZED\");\n\n getApproved[id] = spender;\n\n emit Approval(owner, spender, id);\n }\n\n function setApprovalForAll(address operator, bool approved) public virtual {\n isApprovedForAll[msg.sender][operator] = approved;\n\n emit ApprovalForAll(msg.sender, operator, approved);\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n require(from == _ownerOf[id], \"WRONG_FROM\");\n\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(\n msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],\n \"NOT_AUTHORIZED\"\n );\n\n // Underflow of the sender's balance is impossible because we check for\n // ownership above and the recipient's balance can't realistically overflow.\n unchecked {\n _balanceOf[from]--;\n\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n delete getApproved[id];\n\n emit Transfer(from, to, id);\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n bytes calldata data\n ) public virtual {\n transferFrom(from, to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return\n interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165\n interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721\n interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 id) internal virtual {\n require(to != address(0), \"INVALID_RECIPIENT\");\n\n require(_ownerOf[id] == address(0), \"ALREADY_MINTED\");\n\n // Counter overflow is incredibly unrealistic.\n unchecked {\n _balanceOf[to]++;\n }\n\n _ownerOf[id] = to;\n\n emit Transfer(address(0), to, id);\n }\n\n function _burn(uint256 id) internal virtual {\n address owner = _ownerOf[id];\n\n require(owner != address(0), \"NOT_MINTED\");\n\n // Ownership check above ensures no underflow.\n unchecked {\n _balanceOf[owner]--;\n }\n\n delete _ownerOf[id];\n\n delete getApproved[id];\n\n emit Transfer(owner, address(0), id);\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL SAFE MINT LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _safeMint(address to, uint256 id) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, \"\") ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n\n function _safeMint(\n address to,\n uint256 id,\n bytes memory data\n ) internal virtual {\n _mint(to, id);\n\n if (to.code.length != 0)\n require(\n ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==\n ERC721TokenReceiver.onERC721Received.selector,\n \"UNSAFE_RECIPIENT\"\n );\n }\n}\n\n/// @notice A generic interface for a contract which properly accepts ERC721 tokens.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721TokenReceiver {\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n ) external virtual returns (bytes4) {\n return ERC721TokenReceiver.onERC721Received.selector;\n }\n}\n" + }, + "contracts/testing/helpers/TestERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n constructor() ERC20(\"TEST\", \"TST\", 18) {}\n\n function mint(address to, uint256 value) public {\n _mint(to, value);\n }\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "contracts/L1/TeleportrWithdrawer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AssetReceiver } from \"../universal/AssetReceiver.sol\";\n\n/**\n * @notice Stub interface for Teleportr.\n */\ninterface Teleportr {\n function withdrawBalance() external;\n}\n\n/**\n * @title TeleportrWithdrawer\n * @notice The TeleportrWithdrawer is a simple contract capable of withdrawing funds from the\n * TeleportrContract and sending them to some recipient address.\n */\ncontract TeleportrWithdrawer is AssetReceiver {\n /**\n * @notice Address of the Teleportr contract.\n */\n address public teleportr;\n\n /**\n * @notice Address that will receive Teleportr withdrawals.\n */\n address public recipient;\n\n /**\n * @notice Data to be sent to the recipient address.\n */\n bytes public data;\n\n /**\n * @param _owner Initial owner of the contract.\n */\n constructor(address _owner) AssetReceiver(_owner) {}\n\n /**\n * @notice Allows the owner to update the recipient address.\n *\n * @param _recipient New recipient address.\n */\n function setRecipient(address _recipient) external onlyOwner {\n recipient = _recipient;\n }\n\n /**\n * @notice Allows the owner to update the Teleportr contract address.\n *\n * @param _teleportr New Teleportr contract address.\n */\n function setTeleportr(address _teleportr) external onlyOwner {\n teleportr = _teleportr;\n }\n\n /**\n * @notice Allows the owner to update the data to be sent to the recipient address.\n *\n * @param _data New data to be sent to the recipient address.\n */\n function setData(bytes memory _data) external onlyOwner {\n data = _data;\n }\n\n /**\n * @notice Withdraws the full balance of the Teleportr contract to the recipient address.\n * Anyone is allowed to trigger this function since the recipient address cannot be\n * controlled by the msg.sender.\n */\n function withdrawFromTeleportr() external {\n Teleportr(teleportr).withdrawBalance();\n (bool success, ) = recipient.call{ value: address(this).balance }(data);\n require(success, \"TeleportrWithdrawer: send failed\");\n }\n}\n" + }, + "contracts/universal/AssetReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\nimport { Transactor } from \"./Transactor.sol\";\n\n/**\n * @title AssetReceiver\n * @notice AssetReceiver is a minimal contract for receiving funds assets in the form of either\n * ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.\n */\ncontract AssetReceiver is Transactor {\n /**\n * @notice Emitted when ETH is received by this address.\n *\n * @param from Address that sent ETH to this contract.\n * @param amount Amount of ETH received.\n */\n event ReceivedETH(address indexed from, uint256 amount);\n\n /**\n * @notice Emitted when ETH is withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param amount ETH amount withdrawn.\n */\n event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param amount ERC20 amount withdrawn.\n */\n event WithdrewERC20(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 amount\n );\n\n /**\n * @notice Emitted when ERC20 tokens are withdrawn from this address.\n *\n * @param withdrawer Address that triggered the withdrawal.\n * @param recipient Address that received the withdrawal.\n * @param asset Address of the token being withdrawn.\n * @param id Token ID being withdrawn.\n */\n event WithdrewERC721(\n address indexed withdrawer,\n address indexed recipient,\n address indexed asset,\n uint256 id\n );\n\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Transactor(_owner) {}\n\n /**\n * @notice Make sure we can receive ETH.\n */\n receive() external payable {\n emit ReceivedETH(msg.sender, msg.value);\n }\n\n /**\n * @notice Withdraws full ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n */\n function withdrawETH(address payable _to) external onlyOwner {\n withdrawETH(_to, address(this).balance);\n }\n\n /**\n * @notice Withdraws partial ETH balance to the recipient.\n *\n * @param _to Address to receive the ETH balance.\n * @param _amount Amount of ETH to withdraw.\n */\n function withdrawETH(address payable _to, uint256 _amount) public onlyOwner {\n // slither-disable-next-line reentrancy-unlimited-gas\n (bool success, ) = _to.call{ value: _amount }(\"\");\n emit WithdrewETH(msg.sender, _to, _amount);\n }\n\n /**\n * @notice Withdraws full ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n */\n function withdrawERC20(ERC20 _asset, address _to) external onlyOwner {\n withdrawERC20(_asset, _to, _asset.balanceOf(address(this)));\n }\n\n /**\n * @notice Withdraws partial ERC20 balance to the recipient.\n *\n * @param _asset ERC20 token to withdraw.\n * @param _to Address to receive the ERC20 balance.\n * @param _amount Amount of ERC20 to withdraw.\n */\n function withdrawERC20(\n ERC20 _asset,\n address _to,\n uint256 _amount\n ) public onlyOwner {\n // slither-disable-next-line unchecked-transfer\n _asset.transfer(_to, _amount);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC20(msg.sender, _to, address(_asset), _amount);\n }\n\n /**\n * @notice Withdraws ERC721 token to the recipient.\n *\n * @param _asset ERC721 token to withdraw.\n * @param _to Address to receive the ERC721 token.\n * @param _id Token ID of the ERC721 token to withdraw.\n */\n function withdrawERC721(\n ERC721 _asset,\n address _to,\n uint256 _id\n ) external onlyOwner {\n _asset.transferFrom(address(this), _to, _id);\n // slither-disable-next-line reentrancy-events\n emit WithdrewERC721(msg.sender, _to, address(_asset), _id);\n }\n}\n" + }, + "contracts/universal/Transactor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\n\n/**\n * @title Transactor\n * @notice Transactor is a minimal contract that can send transactions.\n */\ncontract Transactor is Owned {\n /**\n * @param _owner Initial contract owner.\n */\n constructor(address _owner) Owned(_owner) {}\n\n /**\n * Sends a CALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n * @param _value ETH value to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function CALL(\n address _target,\n bytes memory _data,\n uint256 _value\n ) external payable onlyOwner returns (bool, bytes memory) {\n return _target.call{ value: _value }(_data);\n }\n\n /**\n * Sends a DELEGATECALL to a target address.\n *\n * @param _target Address to call.\n * @param _data Data to send with the call.\n *\n * @return Boolean success value.\n * @return Bytes data returned by the call.\n */\n function DELEGATECALL(address _target, bytes memory _data)\n external\n payable\n onlyOwner\n returns (bool, bytes memory)\n {\n // slither-disable-next-line controlled-delegatecall\n return _target.delegatecall(_data);\n }\n}\n" + }, + "contracts/L2/TeleportrDisburser.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title TeleportrDisburser\n */\ncontract TeleportrDisburser is Ownable {\n /**\n * @notice A struct holding the address and amount to disbursement.\n */\n struct Disbursement {\n uint256 amount;\n address addr;\n }\n\n /**\n * @notice Total number of disbursements processed.\n */\n uint256 public totalDisbursements;\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a disbursement is successfuly sent.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The recipient of the disbursement.\n * @param amount The amount sent to the recipient.\n */\n event DisbursementSuccess(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @notice Emitted any time a disbursement fails to send.\n *\n * @param depositId The unique sequence number identifying the deposit.\n * @param to The intended recipient of the disbursement.\n * @param amount The amount intended to be sent to the recipient.\n */\n event DisbursementFailed(uint256 indexed depositId, address indexed to, uint256 amount);\n\n /**\n * @custom:semver 0.0.1\n */\n constructor() {\n totalDisbursements = 0;\n }\n\n /**\n * @notice Accepts a list of Disbursements and forwards the amount paid to the contract to each\n * recipient. Reverts if there are zero disbursements, the total amount to forward\n * differs from the amount sent in the transaction, or the _nextDepositId is\n * unexpected. Failed disbursements will not cause the method to revert, but will\n * instead be held by the contract and available for the owner to withdraw.\n *\n * @param _nextDepositId The depositId of the first Dispursement.\n * @param _disbursements A list of Disbursements to process.\n */\n function disburse(uint256 _nextDepositId, Disbursement[] calldata _disbursements)\n external\n payable\n onlyOwner\n {\n // Ensure there are disbursements to process.\n uint256 _numDisbursements = _disbursements.length;\n require(_numDisbursements > 0, \"No disbursements\");\n\n // Ensure the _nextDepositId matches our expected value.\n uint256 _depositId = totalDisbursements;\n require(_depositId == _nextDepositId, \"Unexpected next deposit id\");\n unchecked {\n totalDisbursements += _numDisbursements;\n }\n\n // Ensure the amount sent in the transaction is equal to the sum of the\n // disbursements.\n uint256 _totalDisbursed = 0;\n for (uint256 i = 0; i < _numDisbursements; i++) {\n _totalDisbursed += _disbursements[i].amount;\n }\n require(_totalDisbursed == msg.value, \"Disbursement total != amount sent\");\n\n // Process disbursements.\n for (uint256 i = 0; i < _numDisbursements; i++) {\n uint256 _amount = _disbursements[i].amount;\n address _addr = _disbursements[i].addr;\n\n // Deliver the dispursement amount to the receiver. If the\n // disbursement fails, the amount will be kept by the contract\n // rather than reverting to prevent blocking progress on other\n // disbursements.\n\n // slither-disable-next-line calls-loop,reentrancy-events\n (bool success, ) = _addr.call{ value: _amount, gas: 2300 }(\"\");\n if (success) emit DisbursementSuccess(_depositId, _addr, _amount);\n else emit DisbursementFailed(_depositId, _addr, _amount);\n\n unchecked {\n _depositId += 1;\n }\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 balance = address(this).balance;\n emit BalanceWithdrawn(_owner, balance);\n payable(_owner).transfer(balance);\n }\n}\n" + }, + "contracts/L1/TeleportrDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:attribution https://github.com/0xclem/teleportr\n * @title TeleportrDeposit\n * @notice A contract meant to manage deposits into Optimism's Teleportr custodial bridge. Deposits\n * are rate limited to avoid a situation where too much ETH is flowing through this bridge\n * and cannot be properly disbursed on L2. Inspired by 0xclem's original Teleportr system\n * (https://github.com/0xclem/teleportr).\n */\ncontract TeleportrDeposit is Ownable {\n /**\n * @notice Minimum deposit amount (in wei).\n */\n uint256 public minDepositAmount;\n\n /**\n * @notice Maximum deposit amount (in wei).\n */\n uint256 public maxDepositAmount;\n\n /**\n * @notice Maximum balance this contract will hold before it starts rejecting deposits.\n */\n uint256 public maxBalance;\n\n /**\n * @notice Total number of deposits received.\n */\n uint256 public totalDeposits;\n\n /**\n * @notice Emitted any time the minimum deposit amount is set.\n *\n * @param previousAmount The previous minimum deposit amount.\n * @param newAmount The new minimum deposit amount.\n */\n event MinDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the maximum deposit amount is set.\n *\n * @param previousAmount The previous maximum deposit amount.\n * @param newAmount The new maximum deposit amount.\n */\n event MaxDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n /**\n * @notice Emitted any time the contract maximum balance is set.\n *\n * @param previousBalance The previous maximum contract balance.\n * @param newBalance The new maximum contract balance.\n */\n event MaxBalanceSet(uint256 previousBalance, uint256 newBalance);\n\n /**\n * @notice Emitted any time the balance is withdrawn by the owner.\n *\n * @param owner The current owner and recipient of the funds.\n * @param balance The current contract balance paid to the owner.\n */\n event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n /**\n * @notice Emitted any time a successful deposit is received.\n *\n * @param depositId A unique sequencer number identifying the deposit.\n * @param emitter The sending address of the payer.\n * @param amount The amount deposited by the payer.\n */\n event EtherReceived(uint256 indexed depositId, address indexed emitter, uint256 indexed amount);\n\n /**\n * @custom:semver 0.0.1\n *\n * @param _minDepositAmount The initial minimum deposit amount.\n * @param _maxDepositAmount The initial maximum deposit amount.\n * @param _maxBalance The initial maximum contract balance.\n */\n constructor(\n uint256 _minDepositAmount,\n uint256 _maxDepositAmount,\n uint256 _maxBalance\n ) {\n minDepositAmount = _minDepositAmount;\n maxDepositAmount = _maxDepositAmount;\n maxBalance = _maxBalance;\n totalDeposits = 0;\n emit MinDepositAmountSet(0, _minDepositAmount);\n emit MaxDepositAmountSet(0, _maxDepositAmount);\n emit MaxBalanceSet(0, _maxBalance);\n }\n\n /**\n * @notice Accepts deposits that will be disbursed to the sender's address on L2.\n */\n receive() external payable {\n require(msg.value >= minDepositAmount, \"Deposit amount is too small\");\n require(msg.value <= maxDepositAmount, \"Deposit amount is too big\");\n require(address(this).balance <= maxBalance, \"Contract max balance exceeded\");\n\n emit EtherReceived(totalDeposits, msg.sender, msg.value);\n unchecked {\n totalDeposits += 1;\n }\n }\n\n /**\n * @notice Sends the contract's current balance to the owner.\n */\n function withdrawBalance() external onlyOwner {\n address _owner = owner();\n uint256 _balance = address(this).balance;\n emit BalanceWithdrawn(_owner, _balance);\n payable(_owner).transfer(_balance);\n }\n\n /**\n * @notice Sets the minimum amount that can be deposited in a receive.\n *\n * @param _minDepositAmount The new minimum deposit amount.\n */\n function setMinAmount(uint256 _minDepositAmount) external onlyOwner {\n emit MinDepositAmountSet(minDepositAmount, _minDepositAmount);\n minDepositAmount = _minDepositAmount;\n }\n\n /**\n * @notice Sets the maximum amount that can be deposited in a receive.\n *\n * @param _maxDepositAmount The new maximum deposit amount.\n */\n function setMaxAmount(uint256 _maxDepositAmount) external onlyOwner {\n emit MaxDepositAmountSet(maxDepositAmount, _maxDepositAmount);\n maxDepositAmount = _maxDepositAmount;\n }\n\n /**\n * @notice Sets the maximum balance the contract can hold after a receive.\n *\n * @param _maxBalance The new maximum contract balance.\n */\n function setMaxBalance(uint256 _maxBalance) external onlyOwner {\n emit MaxBalanceSet(maxBalance, _maxBalance);\n maxBalance = _maxBalance;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/contracts-periphery/hardhat.config.ts b/packages/contracts-periphery/hardhat.config.ts index 856d6b28e08c4..d8f3fb99118fa 100644 --- a/packages/contracts-periphery/hardhat.config.ts +++ b/packages/contracts-periphery/hardhat.config.ts @@ -51,6 +51,9 @@ const config: HardhatUserConfig = { apiKey: getenv('OPTIMISTIC_ETHERSCAN_API_KEY'), }, }, + companionNetworks: { + l1: 'ethereum', + }, }, 'optimism-kovan': { chainId: 69, @@ -61,6 +64,9 @@ const config: HardhatUserConfig = { apiKey: getenv('OPTIMISTIC_ETHERSCAN_API_KEY'), }, }, + companionNetworks: { + l1: 'kovan', + }, }, 'optimism-goerli': { chainId: 420, @@ -71,6 +77,9 @@ const config: HardhatUserConfig = { apiKey: getenv('OPTIMISTIC_ETHERSCAN_API_KEY'), }, }, + companionNetworks: { + l1: 'goerli', + }, }, ethereum: { chainId: 1, @@ -81,6 +90,9 @@ const config: HardhatUserConfig = { apiKey: getenv('ETHEREUM_ETHERSCAN_API_KEY'), }, }, + companionNetworks: { + l2: 'optimism', + }, }, goerli: { chainId: 5, @@ -91,6 +103,9 @@ const config: HardhatUserConfig = { apiKey: getenv('ETHEREUM_ETHERSCAN_API_KEY'), }, }, + companionNetworks: { + l2: 'optimism-goerli', + }, }, ropsten: { chainId: 3, @@ -111,6 +126,9 @@ const config: HardhatUserConfig = { apiKey: getenv('ETHEREUM_ETHERSCAN_API_KEY'), }, }, + companionNetworks: { + l2: 'optimism-kovan', + }, }, 'ops-l2': { chainId: 17, @@ -119,6 +137,9 @@ const config: HardhatUserConfig = { '0xa6aecc98b63bafb0de3b29ae9964b14acb4086057808be29f90150214ebd4a0f', ], url: 'http://127.0.0.1:8545', + companionNetworks: { + l1: 'ops-l1', + }, }, 'ops-l1': { chainId: 31337, @@ -126,11 +147,26 @@ const config: HardhatUserConfig = { '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', ], url: 'http://127.0.0.1:9545', + companionNetworks: { + l2: 'ops-l2', + }, }, }, paths: { deployConfig: './config/deploy', }, + external: { + contracts: [ + { + artifacts: '../contracts/artifacts', + }, + ], + deployments: { + goerli: ['../contracts/deployments/goerli'], + kovan: ['../contracts/deployments/kovan'], + ethereum: ['../contracts/deployments/mainnet'], + }, + }, deployConfigSpec: configSpec, mocha: { timeout: 50000, diff --git a/packages/contracts-periphery/scripts/deploy-nft-bridge.sh b/packages/contracts-periphery/scripts/deploy-nft-bridge.sh index 7153e853a2350..5879dc6a341c8 100755 --- a/packages/contracts-periphery/scripts/deploy-nft-bridge.sh +++ b/packages/contracts-periphery/scripts/deploy-nft-bridge.sh @@ -20,5 +20,5 @@ npx hardhat deploy --tags L1ERC721BridgeImplementation --network $L1_NETWORK # Step 5: deploy the Proxy for the OptimismMintableERC721Factory to L2 npx hardhat deploy --tags OptimismMintableERC721FactoryProxy --network $L2_NETWORK -# Step 5: deploy the OptimismMintableERC721Factory to L2 +# Step 6: deploy the OptimismMintableERC721Factory to L2 npx hardhat deploy --tags OptimismMintableERC721FactoryImplementation --network $L2_NETWORK diff --git a/packages/contracts-periphery/src/nft-bridge-deploy-helpers.ts b/packages/contracts-periphery/src/nft-bridge-deploy-helpers.ts index 84af7642cb475..5ab01474d8ff0 100644 --- a/packages/contracts-periphery/src/nft-bridge-deploy-helpers.ts +++ b/packages/contracts-periphery/src/nft-bridge-deploy-helpers.ts @@ -14,6 +14,7 @@ export const isTargetL2Network = (network: string): boolean => { case 'optimism': case 'optimism-goerli': case 'ops-l2': + case 'optimism-kovan': return true default: return false @@ -23,8 +24,10 @@ export const isTargetL2Network = (network: string): boolean => { export const isTargetL1Network = (network: string): boolean => { switch (network) { case 'mainnet': + case 'ethereum': case 'goerli': case 'ops-l1': + case 'kovan': return true default: return false @@ -36,7 +39,11 @@ export const getProxyAdmin = (network: string): string => { case 'optimism': return l2MainnetMultisig case 'mainnet': + case 'ethereum': return l1MainnetMultisig + case 'kovan': + case 'optimism-kovan': + return goerliAdmin case 'goerli': case 'optimism-goerli': return goerliAdmin diff --git a/packages/contracts-periphery/test/contracts/universal/OptimismMintableERC721Factory.spec.ts b/packages/contracts-periphery/test/contracts/universal/OptimismMintableERC721Factory.spec.ts index b685e4d094f92..997c9d02fabd5 100644 --- a/packages/contracts-periphery/test/contracts/universal/OptimismMintableERC721Factory.spec.ts +++ b/packages/contracts-periphery/test/contracts/universal/OptimismMintableERC721Factory.spec.ts @@ -76,12 +76,11 @@ describe('OptimismMintableERC721Factory', () => { }) it('should be able to create a standard ERC721 contract', async () => { - const tx = - await OptimismMintableERC721Factory.createStandardOptimismMintableERC721( - L1ERC721.address, - 'L2ERC721', - 'ERC' - ) + const tx = await OptimismMintableERC721Factory.createOptimismMintableERC721( + L1ERC721.address, + 'L2ERC721', + 'ERC' + ) const receipt = await tx.wait() // Get the OptimismMintableERC721Created event @@ -109,7 +108,7 @@ describe('OptimismMintableERC721Factory', () => { expect(await OptimismMintableERC721.baseTokenURI()).to.equal(baseURI) expect( - await OptimismMintableERC721Factory.isStandardOptimismMintableERC721( + await OptimismMintableERC721Factory.isOptimismMintableERC721( OptimismMintableERC721.address ) ).to.equal(true) @@ -117,7 +116,7 @@ describe('OptimismMintableERC721Factory', () => { it('should not be able to create a standard token with a 0 address for l1 token', async () => { await expect( - OptimismMintableERC721Factory.createStandardOptimismMintableERC721( + OptimismMintableERC721Factory.createOptimismMintableERC721( ethers.constants.AddressZero, 'L2ERC721', 'ERC' diff --git a/packages/contracts/deployments/goerli/README.md b/packages/contracts/deployments/goerli/README.md index 63aa30567aef5..1308f5bcc791e 100644 --- a/packages/contracts/deployments/goerli/README.md +++ b/packages/contracts/deployments/goerli/README.md @@ -90,8 +90,8 @@ Proxy__OVM_L1StandardBridge StateCommitmentChain - -0x72281826E90dD8A65Ab686fF254eb45Be426DD22 + +0x9c945aC97Baf48cB784AbBB61399beB71aF7A378 @@ -190,4 +190,3 @@ WETH9 - diff --git a/packages/sdk/hardhat.config.ts b/packages/sdk/hardhat.config.ts index 54377930c081c..bd69156a2e18d 100644 --- a/packages/sdk/hardhat.config.ts +++ b/packages/sdk/hardhat.config.ts @@ -25,6 +25,10 @@ const config: HardhatUserConfig = { url: process.env.L1_RPC || '', accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero], }, + goerli: { + url: process.env.L1_RPC || '', + accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero], + }, }, external: { contracts: [ @@ -35,7 +39,10 @@ const config: HardhatUserConfig = { deployments: { hivenet: ['../contracts-bedrock/deployments/hivenet'], devnetL1: ['../contracts-bedrock/deployments/devnetL1'], - goerli: ['../contracts-bedrock/deployments/goerli'], + goerli: [ + '../contracts-bedrock/deployments/goerli', + '../contracts/deployments/goerli', + ], }, }, } diff --git a/packages/sdk/src/cross-chain-messenger.ts b/packages/sdk/src/cross-chain-messenger.ts index 567bf1e748a04..39eaec0aee969 100644 --- a/packages/sdk/src/cross-chain-messenger.ts +++ b/packages/sdk/src/cross-chain-messenger.ts @@ -1212,30 +1212,30 @@ export class CrossChainMessenger { ) interface WithdrawalEntry { - withdrawalInitiated: any - withdrawalInitiatedExtension1: any + MessagePassed: any + MessagePassedExtension1: any } // Handle multiple withdrawals in the same tx and be backwards - // compatible without WithdrawalInitiatedExtension1 + // compatible without MessagePassedExtension1 const logs: Partial<{ number: WithdrawalEntry }> = {} for (const [i, log] of Object.entries(receipt.logs)) { if (log.address === this.contracts.l2.BedrockMessagePasser.address) { const decoded = this.contracts.l2.L2ToL1MessagePasser.interface.parseLog(log) // Find the withdrawal initiated events - if (decoded.name === 'WithdrawalInitiated') { + if (decoded.name === 'MessagePassed') { logs[log.logIndex] = { - withdrawalInitiated: decoded.args, - withdrawalInitiatedExtension1: null, + MessagePassed: decoded.args, + MessagePassedExtension1: null, } if (receipt.logs[i + 1]) { const next = this.contracts.l2.L2ToL1MessagePasser.interface.parseLog( receipt.logs[i + 1] ) - if (next.name === 'WithdrawalInitiatedExtension1') { - logs[log.logIndex].withdrawalInitiatedExtension1 = next.args + if (next.name === 'MessagePassedExtension1') { + logs[log.logIndex].MessagePassedExtension1 = next.args } } } @@ -1252,17 +1252,17 @@ export class CrossChainMessenger { } const withdrawalHash = hashWithdrawal( - withdrawal.withdrawalInitiated.nonce, - withdrawal.withdrawalInitiated.sender, - withdrawal.withdrawalInitiated.target, - withdrawal.withdrawalInitiated.value, - withdrawal.withdrawalInitiated.gasLimit, - withdrawal.withdrawalInitiated.data + withdrawal.MessagePassed.nonce, + withdrawal.MessagePassed.sender, + withdrawal.MessagePassed.target, + withdrawal.MessagePassed.value, + withdrawal.MessagePassed.gasLimit, + withdrawal.MessagePassed.data ) // Sanity check - if (withdrawal.withdrawalInitiatedExtension1) { - if (withdrawal.withdrawalInitiatedExtension1.hash !== withdrawalHash) { + if (withdrawal.MessagePassedExtension1) { + if (withdrawal.MessagePassedExtension1.hash !== withdrawalHash) { throw new Error(`Mismatched withdrawal hashes`) } } @@ -1314,12 +1314,12 @@ export class CrossChainMessenger { output, // TODO(tynes): use better type, typechain? { - messageNonce: withdrawal.withdrawalInitiated.nonce, - sender: withdrawal.withdrawalInitiated.sender, - target: withdrawal.withdrawalInitiated.target, - value: withdrawal.withdrawalInitiated.value, - minGasLimit: withdrawal.withdrawalInitiated.gasLimit, - message: withdrawal.withdrawalInitiated.data, + messageNonce: withdrawal.MessagePassed.nonce, + sender: withdrawal.MessagePassed.sender, + target: withdrawal.MessagePassed.target, + value: withdrawal.MessagePassed.value, + minGasLimit: withdrawal.MessagePassed.gasLimit, + message: withdrawal.MessagePassed.data, }, ] } diff --git a/packages/sdk/src/interfaces/types.ts b/packages/sdk/src/interfaces/types.ts index bf9c4ecc809f1..08b86dcab3fd2 100644 --- a/packages/sdk/src/interfaces/types.ts +++ b/packages/sdk/src/interfaces/types.ts @@ -30,6 +30,7 @@ export enum L2ChainID { OPTIMISM_HARDHAT_LOCAL = 31337, OPTIMISM_HARDHAT_DEVNET = 17, OPTIMISM_BEDROCK_LOCAL_DEVNET = 901, + OPTIMISM_BEDROCK_ALPHA_TESTNET = 28528, } /** diff --git a/packages/sdk/src/utils/chain-constants.ts b/packages/sdk/src/utils/chain-constants.ts index a6179569be7bc..c94d16e37d256 100644 --- a/packages/sdk/src/utils/chain-constants.ts +++ b/packages/sdk/src/utils/chain-constants.ts @@ -23,6 +23,7 @@ export const DEPOSIT_CONFIRMATION_BLOCKS: { [L2ChainID.OPTIMISM_HARDHAT_LOCAL]: 2 as const, [L2ChainID.OPTIMISM_HARDHAT_DEVNET]: 2 as const, [L2ChainID.OPTIMISM_BEDROCK_LOCAL_DEVNET]: 2 as const, + [L2ChainID.OPTIMISM_BEDROCK_ALPHA_TESTNET]: 12 as const, } export const CHAIN_BLOCK_TIMES: { @@ -146,6 +147,22 @@ export const CONTRACT_ADDRESSES: { }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, + [L2ChainID.OPTIMISM_BEDROCK_ALPHA_TESTNET]: { + l1: { + AddressManager: '0xb4e08DcE1F323608229265c9d4125E22a4B9dbAF' as const, + L1CrossDomainMessenger: + '0x838a6DC4E37CA45D4Ef05bb776bf05eEf50798De' as const, + L1StandardBridge: '0xFf94B6C486350aD92561Ba09bad3a59df764Da92' as const, + StateCommitmentChain: + '0x0000000000000000000000000000000000000000' as const, + CanonicalTransactionChain: + '0x0000000000000000000000000000000000000000' as const, + BondManager: '0x0000000000000000000000000000000000000000' as const, + OptimismPortal: '0xA581Ca3353DB73115C4625FFC7aDF5dB379434A8' as const, + L2OutputOracle: '0x3A234299a14De50027eA65dCdf1c0DaC729e04A6' as const, + }, + l2: DEFAULT_L2_CONTRACT_ADDRESSES, + }, } /** diff --git a/packages/sdk/tasks/finalize-withdrawal.ts b/packages/sdk/tasks/finalize-withdrawal.ts new file mode 100644 index 0000000000000..4abfb5c7499f0 --- /dev/null +++ b/packages/sdk/tasks/finalize-withdrawal.ts @@ -0,0 +1,96 @@ +import { task, types } from 'hardhat/config' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { Wallet, providers } from 'ethers' +import { predeploys } from '@eth-optimism/contracts-bedrock' +import 'hardhat-deploy' +import '@nomiclabs/hardhat-ethers' + +import { + CrossChainMessenger, + StandardBridgeAdapter, + MessageStatus, +} from '../src' + +task('finalize-withdrawal', 'Finalize a withdrawal') + .addParam( + 'transactionHash', + 'L2 Transaction hash to finalize', + '', + types.string + ) + .addParam('l2Url', 'L2 HTTP URL', 'http://localhost:9545', types.string) + .setAction(async (args, hre: HardhatRuntimeEnvironment) => { + const txHash = args.transactionHash + if (txHash === '') { + console.log('No tx hash') + } + + const signers = await hre.ethers.getSigners() + if (signers.length === 0) { + throw new Error('No configured signers') + } + const signer = signers[0] + const address = await signer.getAddress() + console.log(`Using signer: ${address}`) + + const l2Provider = new providers.StaticJsonRpcProvider(args.l2Url) + const l2Signer = new Wallet(hre.network.config.accounts[0], l2Provider) + + let Deployment__L1StandardBridgeProxy = await hre.deployments.getOrNull( + 'L1StandardBridgeProxy' + ) + if (Deployment__L1StandardBridgeProxy === undefined) { + Deployment__L1StandardBridgeProxy = await hre.deployments.getOrNull( + 'Proxy__OVM_L1StandardBridge' + ) + } + + let Deployment__L1CrossDomainMessengerProxy = + await hre.deployments.getOrNull('L1CrossDomainMessengerProxy') + if (Deployment__L1CrossDomainMessengerProxy === undefined) { + Deployment__L1CrossDomainMessengerProxy = await hre.deployments.getOrNull( + 'Proxy__OVM_L1CrossDomainMessenger' + ) + } + + const Deployment__L2OutputOracleProxy = await hre.deployments.getOrNull( + 'L2OutputOracleProxy' + ) + const Deployment__OptimismPortalProxy = await hre.deployments.getOrNull( + 'OptimismPortalProxy' + ) + + const messenger = new CrossChainMessenger({ + l1SignerOrProvider: signer, + l2SignerOrProvider: l2Signer, + l1ChainId: await signer.getChainId(), + l2ChainId: await l2Signer.getChainId(), + bridges: { + Standard: { + Adapter: StandardBridgeAdapter, + l1Bridge: Deployment__L1StandardBridgeProxy?.address, + l2Bridge: predeploys.L2StandardBridge, + }, + }, + contracts: { + l1: { + L1StandardBridge: Deployment__L1StandardBridgeProxy?.address, + L1CrossDomainMessenger: + Deployment__L1CrossDomainMessengerProxy?.address, + L2OutputOracle: Deployment__L2OutputOracleProxy?.address, + OptimismPortal: Deployment__OptimismPortalProxy?.address, + }, + }, + }) + + console.log(`Fetching message status for ${txHash}`) + const status = await messenger.getMessageStatus(txHash) + console.log(`Status: ${MessageStatus[status]}`) + + if (status === MessageStatus.READY_FOR_RELAY) { + const tx = await messenger.finalizeMessage(txHash) + const receipt = await tx.wait() + console.log(receipt) + console.log('Finalized withdrawal') + } + }) diff --git a/packages/sdk/tasks/index.ts b/packages/sdk/tasks/index.ts index c1167380ec60b..270e886b314c9 100644 --- a/packages/sdk/tasks/index.ts +++ b/packages/sdk/tasks/index.ts @@ -1,2 +1,3 @@ import './deposit-eth' import './deposit-erc20' +import './finalize-withdrawal' diff --git a/proxyd/rate_limiter.go b/proxyd/backend_rate_limiter.go similarity index 95% rename from proxyd/rate_limiter.go rename to proxyd/backend_rate_limiter.go index fe286e63b9f5d..03c64361f6838 100644 --- a/proxyd/rate_limiter.go +++ b/proxyd/backend_rate_limiter.go @@ -57,22 +57,14 @@ type RedisBackendRateLimiter struct { tkMtx sync.Mutex } -func NewRedisRateLimiter(url string) (BackendRateLimiter, error) { - opts, err := redis.ParseURL(url) - if err != nil { - return nil, err - } - rdb := redis.NewClient(opts) - if err := rdb.Ping(context.Background()).Err(); err != nil { - return nil, wrapErr(err, "error connecting to redis") - } +func NewRedisRateLimiter(rdb *redis.Client) BackendRateLimiter { out := &RedisBackendRateLimiter{ rdb: rdb, randID: randStr(20), touchKeys: make(map[string]time.Duration), } go out.touch() - return out, nil + return out } func (r *RedisBackendRateLimiter) IsBackendOnline(name string) (bool, error) { diff --git a/proxyd/cache.go b/proxyd/cache.go index 69dbb0b8149ee..73b7fd890acce 100644 --- a/proxyd/cache.go +++ b/proxyd/cache.go @@ -46,16 +46,8 @@ type redisCache struct { rdb *redis.Client } -func newRedisCache(url string) (*redisCache, error) { - opts, err := redis.ParseURL(url) - if err != nil { - return nil, err - } - rdb := redis.NewClient(opts) - if err := rdb.Ping(context.Background()).Err(); err != nil { - return nil, wrapErr(err, "error connecting to redis") - } - return &redisCache{rdb}, nil +func newRedisCache(rdb *redis.Client) *redisCache { + return &redisCache{rdb} } func (c *redisCache) Get(ctx context.Context, key string) (string, error) { diff --git a/proxyd/config.go b/proxyd/config.go index 0647074ab8cb6..d0a32d669cba6 100644 --- a/proxyd/config.go +++ b/proxyd/config.go @@ -41,7 +41,9 @@ type MetricsConfig struct { } type RateLimitConfig struct { - RatePerSecond int `toml:"rate_per_second"` + UseRedis bool `toml:"use_redis"` + BaseRate int `toml:"base_rate"` + BaseInterval TOMLDuration `toml:"base_interval"` ExemptOrigins []string `toml:"exempt_origins"` ExemptUserAgents []string `toml:"exempt_user_agents"` ErrorMessage string `toml:"error_message"` diff --git a/proxyd/frontend_rate_limiter.go b/proxyd/frontend_rate_limiter.go new file mode 100644 index 0000000000000..d377370ed83ff --- /dev/null +++ b/proxyd/frontend_rate_limiter.go @@ -0,0 +1,139 @@ +package proxyd + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/go-redis/redis/v8" +) + +type FrontendRateLimiter interface { + // Take consumes a key, and a maximum number of requests + // per time interval. It returns a boolean denoting if + // the limit could be taken, or an error if a failure + // occurred in the backing rate limit implementation. + // + // No error will be returned if the limit could not be taken + // as a result of the requestor being over the limit. + Take(ctx context.Context, key string) (bool, error) +} + +// limitedKeys is a wrapper around a map that stores a truncated +// timestamp and a mutex. The map is used to keep track of rate +// limit keys, and their used limits. +type limitedKeys struct { + truncTS int64 + keys map[string]int + mtx sync.Mutex +} + +func newLimitedKeys(t int64) *limitedKeys { + return &limitedKeys{ + truncTS: t, + keys: make(map[string]int), + } +} + +func (l *limitedKeys) Take(key string, max int) bool { + l.mtx.Lock() + defer l.mtx.Unlock() + val, ok := l.keys[key] + if !ok { + l.keys[key] = 0 + val = 0 + } + l.keys[key] = val + 1 + return val < max +} + +// MemoryFrontendRateLimiter is a rate limiter that stores +// all rate limiting information in local memory. It works +// by storing a limitedKeys struct that references the +// truncated timestamp at which the struct was created. If +// the current truncated timestamp doesn't match what's +// referenced, the limit is reset. Otherwise, values in +// a map are incremented to represent the limit. +type MemoryFrontendRateLimiter struct { + currGeneration *limitedKeys + dur time.Duration + max int + mtx sync.Mutex +} + +func NewMemoryFrontendRateLimit(dur time.Duration, max int) FrontendRateLimiter { + return &MemoryFrontendRateLimiter{ + dur: dur, + max: max, + } +} + +func (m *MemoryFrontendRateLimiter) Take(ctx context.Context, key string) (bool, error) { + m.mtx.Lock() + // Create truncated timestamp + truncTS := truncateNow(m.dur) + + // If there is no current rate limit map or the rate limit map reference + // a different timestamp, reset limits. + if m.currGeneration == nil || m.currGeneration.truncTS != truncTS { + m.currGeneration = newLimitedKeys(truncTS) + } + + // Pull out the limiter so we can unlock before incrementing the limit. + limiter := m.currGeneration + + m.mtx.Unlock() + + return limiter.Take(key, m.max), nil +} + +// RedisFrontendRateLimiter is a rate limiter that stores data in Redis. +// It uses the basic rate limiter pattern described on the Redis best +// practices website: https://redis.com/redis-best-practices/basic-rate-limiting/. +type RedisFrontendRateLimiter struct { + r *redis.Client + dur time.Duration + max int + prefix string +} + +func NewRedisFrontendRateLimiter(r *redis.Client, dur time.Duration, max int, prefix string) FrontendRateLimiter { + return &RedisFrontendRateLimiter{ + r: r, + dur: dur, + max: max, + prefix: prefix, + } +} + +func (r *RedisFrontendRateLimiter) Take(ctx context.Context, key string) (bool, error) { + var incr *redis.IntCmd + truncTS := truncateNow(r.dur) + fullKey := fmt.Sprintf("rate_limit:%s:%s:%d", r.prefix, key, truncTS) + _, err := r.r.Pipelined(ctx, func(pipe redis.Pipeliner) error { + incr = pipe.Incr(ctx, fullKey) + pipe.PExpire(ctx, fullKey, r.dur-time.Millisecond) + return nil + }) + if err != nil { + frontendRateLimitTakeErrors.Inc() + return false, err + } + + return incr.Val()-1 < int64(r.max), nil +} + +type noopFrontendRateLimiter struct{} + +var NoopFrontendRateLimiter = &noopFrontendRateLimiter{} + +func (n *noopFrontendRateLimiter) Take(ctx context.Context, key string) (bool, error) { + return true, nil +} + +// truncateNow truncates the current timestamp +// to the specified duration. +func truncateNow(dur time.Duration) int64 { + return time.Now().Truncate(dur).Unix() +} diff --git a/proxyd/frontend_rate_limiter_test.go b/proxyd/frontend_rate_limiter_test.go new file mode 100644 index 0000000000000..f3542cf35109b --- /dev/null +++ b/proxyd/frontend_rate_limiter_test.go @@ -0,0 +1,53 @@ +package proxyd + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/alicebob/miniredis" + "github.com/go-redis/redis/v8" + "github.com/stretchr/testify/require" +) + +func TestFrontendRateLimiter(t *testing.T) { + redisServer, err := miniredis.Run() + require.NoError(t, err) + defer redisServer.Close() + + redisClient := redis.NewClient(&redis.Options{ + Addr: fmt.Sprintf("127.0.0.1:%s", redisServer.Port()), + }) + + max := 2 + lims := []struct { + name string + frl FrontendRateLimiter + }{ + {"memory", NewMemoryFrontendRateLimit(2*time.Second, max)}, + {"redis", NewRedisFrontendRateLimiter(redisClient, 2*time.Second, max, "")}, + } + + for _, cfg := range lims { + frl := cfg.frl + ctx := context.Background() + t.Run(cfg.name, func(t *testing.T) { + for i := 0; i < 4; i++ { + ok, err := frl.Take(ctx, "foo") + require.NoError(t, err) + require.Equal(t, i < max, ok) + ok, err = frl.Take(ctx, "bar") + require.NoError(t, err) + require.Equal(t, i < max, ok) + } + time.Sleep(2 * time.Second) + for i := 0; i < 4; i++ { + ok, _ := frl.Take(ctx, "foo") + require.Equal(t, i < max, ok) + ok, _ = frl.Take(ctx, "bar") + require.Equal(t, i < max, ok) + } + }) + } +} diff --git a/proxyd/integration_tests/failover_test.go b/proxyd/integration_tests/failover_test.go index f80f47c723001..47c9e2667be1b 100644 --- a/proxyd/integration_tests/failover_test.go +++ b/proxyd/integration_tests/failover_test.go @@ -261,6 +261,8 @@ func TestInfuraFailoverOnUnexpectedResponse(t *testing.T) { config.BackendOptions.MaxRetries = 2 // Setup redis to detect offline backends config.Redis.URL = fmt.Sprintf("redis://127.0.0.1:%s", redis.Port()) + redisClient, err := proxyd.NewRedisClient(config.Redis.URL) + require.NoError(t, err) goodBackend := NewMockBackend(BatchedResponseHandler(200, goodResponse, goodResponse)) defer goodBackend.Close() @@ -285,7 +287,7 @@ func TestInfuraFailoverOnUnexpectedResponse(t *testing.T) { require.Equal(t, 1, len(badBackend.Requests())) require.Equal(t, 1, len(goodBackend.Requests())) - rr, err := proxyd.NewRedisRateLimiter(config.Redis.URL) + rr := proxyd.NewRedisRateLimiter(redisClient) require.NoError(t, err) online, err := rr.IsBackendOnline("bad") require.NoError(t, err) diff --git a/proxyd/integration_tests/testdata/frontend_rate_limit.toml b/proxyd/integration_tests/testdata/frontend_rate_limit.toml index f34840dab6b94..affb855e11c9c 100644 --- a/proxyd/integration_tests/testdata/frontend_rate_limit.toml +++ b/proxyd/integration_tests/testdata/frontend_rate_limit.toml @@ -18,7 +18,8 @@ eth_chainId = "main" eth_foobar = "main" [rate_limit] -rate_per_second = 2 +base_rate = 2 +base_interval = "1s" exempt_origins = ["exempt_origin"] exempt_user_agents = ["exempt_agent"] error_message = "over rate limit with special message" diff --git a/proxyd/metrics.go b/proxyd/metrics.go index a3cfe45035892..06fef153c8c87 100644 --- a/proxyd/metrics.go +++ b/proxyd/metrics.go @@ -236,6 +236,12 @@ var ( 100, }, }) + + frontendRateLimitTakeErrors = promauto.NewCounter(prometheus.CounterOpts{ + Namespace: MetricsNamespace, + Name: "rate_limit_take_errors", + Help: "Count of errors taking frontend rate limits", + }) ) func RecordRedisError(source string) { diff --git a/proxyd/proxyd.go b/proxyd/proxyd.go index 12a6a1a834b58..5685633cb7793 100644 --- a/proxyd/proxyd.go +++ b/proxyd/proxyd.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" + "github.com/go-redis/redis/v8" "github.com/prometheus/client_golang/prometheus/promhttp" "golang.org/x/sync/semaphore" ) @@ -34,25 +35,29 @@ func Start(config *Config) (func(), error) { } } - var redisURL string + var redisClient *redis.Client if config.Redis.URL != "" { rURL, err := ReadFromEnvOrConfig(config.Redis.URL) if err != nil { return nil, err } - redisURL = rURL + redisClient, err = NewRedisClient(rURL) + if err != nil { + return nil, err + } + } + + if redisClient == nil && config.RateLimit.UseRedis { + return nil, errors.New("must specify a Redis URL if UseRedis is true in rate limit config") } var lim BackendRateLimiter var err error - if redisURL == "" { + if redisClient == nil { log.Warn("redis is not configured, using local rate limiter") lim = NewLocalBackendRateLimiter() } else { - lim, err = NewRedisRateLimiter(redisURL) - if err != nil { - return nil, err - } + lim = NewRedisRateLimiter(redisClient) } // While modifying shared globals is a bad practice, the alternative @@ -206,13 +211,11 @@ func Start(config *Config) (func(), error) { return nil, err } - if redisURL != "" { - if cache, err = newRedisCache(redisURL); err != nil { - return nil, err - } - } else { + if redisClient == nil { log.Warn("redis is not configured, using in-memory cache") cache = newMemoryCache() + } else { + cache = newRedisCache(redisClient) } // Ideally, the BlocKSyncRPCURL should be the sequencer or a HA replica that's not far behind ethClient, err := ethclient.Dial(blockSyncRPCURL) @@ -240,6 +243,7 @@ func Start(config *Config) (func(), error) { config.Server.EnableRequestLog, config.Server.MaxRequestBodyLogLen, config.BatchConfig.MaxSize, + redisClient, ) if err != nil { return nil, fmt.Errorf("error creating server: %w", err) diff --git a/proxyd/redis.go b/proxyd/redis.go new file mode 100644 index 0000000000000..e32bff243243f --- /dev/null +++ b/proxyd/redis.go @@ -0,0 +1,22 @@ +package proxyd + +import ( + "context" + "time" + + "github.com/go-redis/redis/v8" +) + +func NewRedisClient(url string) (*redis.Client, error) { + opts, err := redis.ParseURL(url) + if err != nil { + return nil, err + } + client := redis.NewClient(opts) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := client.Ping(ctx).Err(); err != nil { + return nil, wrapErr(err, "error connecting to redis") + } + return client, nil +} diff --git a/proxyd/rpc.go b/proxyd/rpc.go index e34b01041fb90..0c30d6439d883 100644 --- a/proxyd/rpc.go +++ b/proxyd/rpc.go @@ -57,6 +57,7 @@ func (r *RPCRes) MarshalJSON() ([]byte, error) { type RPCErr struct { Code int `json:"code"` Message string `json:"message"` + Data string `json:"data,omitempty"` HTTPErrorCode int `json:"-"` } diff --git a/proxyd/rpc_test.go b/proxyd/rpc_test.go index 0d38decf08bd9..e30fe9361a6b2 100644 --- a/proxyd/rpc_test.go +++ b/proxyd/rpc_test.go @@ -45,7 +45,7 @@ func TestRPCResJSON(t *testing.T) { `{"jsonrpc":"2.0","result":null,"id":123}`, }, { - "error result", + "error result without data", &RPCRes{ JSONRPC: JSONRPCVersion, Error: &RPCErr{ @@ -56,6 +56,19 @@ func TestRPCResJSON(t *testing.T) { }, `{"jsonrpc":"2.0","error":{"code":1234,"message":"test err"},"id":123}`, }, + { + "error result with data", + &RPCRes{ + JSONRPC: JSONRPCVersion, + Error: &RPCErr{ + Code: 1234, + Message: "test err", + Data: "revert", + }, + ID: []byte("123"), + }, + `{"jsonrpc":"2.0","error":{"code":1234,"message":"test err","data":"revert"},"id":123}`, + }, { "string ID", &RPCRes{ diff --git a/proxyd/server.go b/proxyd/server.go index 94787d1b1321c..e86ba4c4bf6ad 100644 --- a/proxyd/server.go +++ b/proxyd/server.go @@ -13,11 +13,8 @@ import ( "sync" "time" - "github.com/sethvargo/go-limiter" - "github.com/sethvargo/go-limiter/memorystore" - "github.com/sethvargo/go-limiter/noopstore" - "github.com/ethereum/go-ethereum/log" + "github.com/go-redis/redis/v8" "github.com/gorilla/mux" "github.com/gorilla/websocket" "github.com/prometheus/client_golang/prometheus" @@ -50,9 +47,8 @@ type Server struct { maxUpstreamBatchSize int maxBatchSize int upgrader *websocket.Upgrader - mainLim limiter.Store - overrideLims map[string]limiter.Store - limConfig RateLimitConfig + mainLim FrontendRateLimiter + overrideLims map[string]FrontendRateLimiter limExemptOrigins map[string]bool limExemptUserAgents map[string]bool rpcServer *http.Server @@ -77,6 +73,7 @@ func NewServer( enableRequestLog bool, maxRequestBodyLogLen int, maxBatchSize int, + redisClient *redis.Client, ) (*Server, error) { if cache == nil { cache = &NoopRPCCache{} @@ -98,19 +95,19 @@ func NewServer( maxBatchSize = MaxBatchRPCCallsHardLimit } - var mainLim limiter.Store - limExemptOrigins := make(map[string]bool) - limExemptUserAgents := make(map[string]bool) - if rateLimitConfig.RatePerSecond > 0 { - var err error - mainLim, err = memorystore.New(&memorystore.Config{ - Tokens: uint64(rateLimitConfig.RatePerSecond), - Interval: time.Second, - }) - if err != nil { - return nil, err + limiterFactory := func(dur time.Duration, max int, prefix string) FrontendRateLimiter { + if rateLimitConfig.UseRedis { + return NewRedisFrontendRateLimiter(redisClient, dur, max, prefix) } + return NewMemoryFrontendRateLimit(dur, max) + } + + var mainLim FrontendRateLimiter + limExemptOrigins := make(map[string]bool) + limExemptUserAgents := make(map[string]bool) + if rateLimitConfig.BaseRate > 0 { + mainLim = limiterFactory(time.Duration(rateLimitConfig.BaseInterval), rateLimitConfig.BaseRate, "main") for _, origin := range rateLimitConfig.ExemptOrigins { limExemptOrigins[strings.ToLower(origin)] = true } @@ -118,16 +115,13 @@ func NewServer( limExemptUserAgents[strings.ToLower(agent)] = true } } else { - mainLim, _ = noopstore.New() + mainLim = NoopFrontendRateLimiter } - overrideLims := make(map[string]limiter.Store) + overrideLims := make(map[string]FrontendRateLimiter) for method, override := range rateLimitConfig.MethodOverrides { var err error - overrideLims[method], err = memorystore.New(&memorystore.Config{ - Tokens: uint64(override.Limit), - Interval: time.Duration(override.Interval), - }) + overrideLims[method] = limiterFactory(time.Duration(override.Interval), override.Limit, method) if err != nil { return nil, err } @@ -151,7 +145,6 @@ func NewServer( }, mainLim: mainLim, overrideLims: overrideLims, - limConfig: rateLimitConfig, limExemptOrigins: limExemptOrigins, limExemptUserAgents: limExemptUserAgents, }, nil @@ -235,7 +228,7 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) { return false } - var lim limiter.Store + var lim FrontendRateLimiter if method == "" { lim = s.mainLim } else { @@ -246,7 +239,11 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) { return false } - _, _, _, ok, _ := lim.Take(ctx, xff) + ok, err := lim.Take(ctx, xff) + if err != nil { + log.Warn("error taking rate limit", "err", err) + return true + } return !ok } diff --git a/specs/withdrawals.md b/specs/withdrawals.md index 3bbe1ac690dbb..37f01053c1f21 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -78,7 +78,7 @@ which stores messages to be withdrawn. ```js interface L2ToL1MessagePasser { - event WithdrawalInitiated( + event MessagePassed( uint256 indexed nonce, // this is a global nonce value for all withdrawal messages address indexed sender, address indexed target, @@ -87,7 +87,7 @@ interface L2ToL1MessagePasser { bytes data ); - event WithdrawalInitiatedExtension1(bytes32 indexed hash); + event MessagePassedExtension1(bytes32 indexed hash); event WithdrawerBalanceBurnt(uint256 indexed amount); @@ -102,8 +102,8 @@ interface L2ToL1MessagePasser { ``` -The `WithdrawalInitiated` event includes all of the data that is hashed and -stored in the `sentMessages` mapping. The `WithdrawalInitiatedExtension1` emits +The `MessagePassed` event includes all of the data that is hashed and +stored in the `sentMessages` mapping. The `MessagePassedExtension1` emits the hash that was computed and used as part of the storage proof used to finalize the withdrawal on L1.